public override Bounds Bounds(RenderEntity ent) { Bounds b = new(); b.Zero(); b.ExpandSelf(ent == null ? 8f : Math.Max(ent.shaderParms[IRenderWorld.SHADERPARM_SPRITE_WIDTH], ent.shaderParms[IRenderWorld.SHADERPARM_SPRITE_HEIGHT]) * 0.5f); return(b); }
public RenderBuffer <float> Draw(RenderEntity[] entities, ICamera camera) { _renderTarget.Clear(); _matrixWorldToView = camera.WorldToView; TApp appdata = new TApp(); TV2F[][] vertexV2FData = new TV2F[entities.Length][]; IPrimitive[][] primitives = new IPrimitive[entities.Length][]; Vector2[][] screenCoords = new Vector2[entities.Length][]; for (int i = 0; i < entities.Length; i++) { RenderEntity instanceCopy = entities[i].GetInstanceToApply(); _matrixObjectToWorld = instanceCopy.Transform.LocalToWorld; _matrixObjectToView = _matrixWorldToView * _matrixObjectToWorld; Vector3[] vertices = instanceCopy.Model.Vertices; vertexV2FData[i] = new TV2F[vertices.Length]; screenCoords[i] = new Vector2[vertices.Length]; primitives[i] = instanceCopy.Model.Primitives; for (int j = 0; j < vertices.Length; j++) { appdata.AssignAppdata(ref instanceCopy.Model, j); TV2F v2f = Vertex(ref appdata); vertexV2FData[i][j] = v2f; screenCoords[i][j] = ViewToScreen(v2f.Vertex_VOut); } } //Octree is so annoying //Clipping(); Vector2Int[][][] rasterization = Rasterize(screenCoords, vertexV2FData, primitives); GenericVector <float> whiteColor = new GenericVector <float>(3) { 1, 1, 1 }; //Model for (int i = 0; i < rasterization.Length; i++) { //Primitive for (int j = 0; j < rasterization[i].Length; j++) { //PixelPos for (int k = 0; k < rasterization[i][j].Length; k++) { _renderTarget.WritePixel(rasterization[i][j][k].X, rasterization[i][j][k].Y, whiteColor); } } } return(_renderTarget); }
private unsafe void SetPerObjectValues(RenderEntity currentEntity) { *ShaderValue.ObjectToWorld = *currentEntity.Transform.LocalToWorld; Mul(ShaderValue.WorldToView, ShaderValue.ObjectToWorld, ShaderValue.ObjectToView); Mul(ViewToScreen, ShaderValue.ObjectToView, ShaderValue.ObjectToScreen); //TODO Normalize //if (!JMath.Approx(ShaderValue.ObjectToView->M44, 1f)) // Divide(ShaderValue.ObjectToView, ShaderValue.ObjectToView->M44, ShaderValue.ObjectToView); }
public static uint CreatePlayer() { int playerCount = ComponentManager.PlayerComponent.Count(); if (playerCount >= MAX_PLAYERS) return uint.MaxValue; uint playerID = IDManager.GetNewID(); Player player = new Player() { EntityID = playerID, PlayerID = (ushort)playerCount }; ComponentManager.PlayerComponent.Add(playerID, player); Position playerPosition = new Position() { EntityID = playerID, Center = new Vector3() }; ComponentManager.PositionComponent.Add(playerID, playerPosition); ComponentManager.PlaneComponent.Add(playerID); Movement playerMovement = new Movement() { EntityID = playerID, MoveDirection = Vector2.zero, Speed = BASE_SPEED }; ComponentManager.MovementComponent.Add(playerID, playerMovement); SpriteAnim playerAnim = new SpriteAnim() { EntityID = playerID, AnimArray = new List<Sprite>(), AnimIndex = 0, AnimType = SpriteType.Loop, FPS = 1.0f, FrameIncrement = 0, TimeLeft = 1.0f }; playerAnim = SpriteHelper.SetMageAnim(playerAnim.EntityID, SpriteHelper.AnimList.IdleDown); ComponentManager.SpriteAnimComponent.Add(playerID, playerAnim); RenderEntity playerRender = new RenderEntity() { EntityID = playerID }; ComponentManager.RenderComponent.Add(playerID, playerRender); return playerID; }
public static void TestRenderCube() { EstablishTestScene <Camera_Orthographic>(out var pipeline, out var charBuffer, out var camera); RenderEntity entity = new RenderEntity( transform: new Transform(Vector3.Zero), model: Model.Cube(), material: null); RenderEntity[] entitiesApply = new RenderEntity[] { entity }; DrawRotatingObject(pipeline, entitiesApply, camera, charBuffer); }
public static void TestRenderTriangle() { EstablishTestScene(out var pipeline, out var charBuffer, out var camera); RenderEntity entity = new RenderEntity(new Transform(), new Model( vertices: new Vector4[] { new Vector4(1, 0, 0, 1), new Vector4(0, 1, 0, 1), new Vector4(0, -1, 0, 1) }, primitives: new IPrimitive[] { new TrianglePrimitive(0, 1, 2) }, uvs: null, normals: null), material: null); RenderEntity[] entitiesApply = new RenderEntity[] { entity }; DrawRotatingObject(pipeline, entitiesApply, camera, charBuffer); }
public static void TestRenderTriangle() { EstablishTestScene <Camera_Orthographic>(out var pipeline, out var charBuffer, out var camera); RenderEntity entity = new RenderEntity( transform: new Transform(Vector3.Zero), new Model( vertices: new Vector3[] { new Vector3(-.5f, -.25f, 0), new Vector3(.5f, -.25f, 0), new Vector3(0, .5f, 0) }, indices: new int[] { 0, 1, 2 }, uvs: null, normals: null), material: null); RenderEntity[] entitiesApply = new RenderEntity[] { entity }; DrawRotatingObject(pipeline, entitiesApply, camera, charBuffer); }
public static void TestDrawLine() { EstablishTestScene(out var pipeline, out var charBuffer, out var camera); RenderEntity entity = new RenderEntity( transform: new Transform(Vector3.Zero), model: new Model( vertices: new Vector4[] { new Vector4(-.5f, .5f, -.5f, 1f), new Vector4(-.5f, -.5f, -.5f, 1f), new Vector4(.5f, -.5f, -.5f, 1f), new Vector4(.5f, .5f, -.5f, 1f), new Vector4(-.5f, .5f, .5f, 1f), new Vector4(-.5f, -.5f, .5f, 1f), new Vector4(.5f, -.5f, .5f, 1f), new Vector4(.5f, .5f, .5f, 1f) }, primitives: new IPrimitive[] { new LinePrimitive(0, 1), new LinePrimitive(1, 2), new LinePrimitive(2, 3), new LinePrimitive(3, 0), new LinePrimitive(4, 5), new LinePrimitive(5, 6), new LinePrimitive(6, 7), new LinePrimitive(7, 4), new LinePrimitive(0, 4), new LinePrimitive(1, 5), new LinePrimitive(2, 6), new LinePrimitive(3, 7) }, uvs: null, normals: null), material: new Material <Shader_Scale>(Shader_Scale.Instance)); RenderEntity[] entitiesApply = new RenderEntity[] { entity }; DrawRotatingObject(pipeline, entitiesApply, camera, charBuffer); }
//void GetFrameBounds(RenderEntity ent, out Bounds bounds); void DrawJoints(RenderEntity ent, ViewDef view) { int i; Vector3 pos; var num = ent.numJoints; for (i = 0; i < num; i++) { var joint = ent.joints[i]; var md5Joint = joints[i]; pos = ent.origin + joint.ToVec3() * ent.axis; if (md5Joint.parent != null) { var parentNum = md5Joint.parent - joints; session.rw.DebugLine(colorWhite, ent.origin + ent.joints[parentNum].ToVec3() * ent.axis, pos); } session.rw.DebugLine(colorRed, pos, pos + joint.ToMat3()[0] * 2f * ent.axis); session.rw.DebugLine(colorGreen, pos, pos + joint.ToMat3()[1] * 2f * ent.axis); session.rw.DebugLine(colorBlue, pos, pos + joint.ToMat3()[2] * 2f * ent.axis); } Bounds bounds = new(); bounds.FromTransformedBounds(ent.bounds, Vector3.origin, ent.axis); session.rw.DebugBounds(colorMagenta, bounds, ent.origin); if (r_jointNameScale.Float != 0f && bounds.Expand(128f).ContainsPoint(view.renderView.vieworg - ent.origin)) { Vector3 offset = new(0f, 0f, r_jointNameOffset.Float); var scale = r_jointNameScale.Float; num = ent.numJoints; for (i = 0; i < num; i++) { var joint = ent.joints[i]; pos = ent.origin + joint.ToVec3() * ent.axis; session.rw.DrawText(joints[i].name, pos + offset, scale, colorWhite, view.renderView.viewaxis, 1); } } }
public static void TestDrawLine() { PipelineBase <AppdataBasic, V2FBasic> pipeline = new PipelineBase <AppdataBasic, V2FBasic>(); CharRenderBuffer <float> charBuffer = new CharRenderBuffer <float>(pipeline.RenderTarget); RenderEntity entity = new RenderEntity(new Transform(Vector3.Zero), new Model( vertices: new Vector3[] { new Vector3(-.5f, .5f, -.5f), new Vector3(-.5f, -.5f, -.5f), new Vector3(.5f, -.5f, -.5f), new Vector3(.5f, .5f, -.5f), new Vector3(-.5f, .5f, .5f), new Vector3(-.5f, -.5f, .5f), new Vector3(.5f, -.5f, .5f), new Vector3(.5f, .5f, .5f) }, primitives: new IPrimitive[] { new LinePrimitive(0, 1), new LinePrimitive(1, 2), new LinePrimitive(2, 3), new LinePrimitive(3, 0), new LinePrimitive(4, 5), new LinePrimitive(5, 6), new LinePrimitive(6, 7), new LinePrimitive(7, 4), new LinePrimitive(0, 4), new LinePrimitive(1, 5), new LinePrimitive(2, 6), new LinePrimitive(3, 7) }, uvs: null, normals: null ), null); ICamera camera = new Camera_Orthographic(width: 3.5f, height: 3.5f, near: -2.5f, far: 2.5f, new Transform( pos: Vector3.Zero, rotation: new Vector3(0, JMath.PI_HALF * .35f, -JMath.PI_HALF * 1.5f))); RenderEntity[] entitiesApply = new RenderEntity[] { entity }; float framerate = 25f; float time = 10f; int totalFrame = (int)(framerate * time); float angleStep = JMath.PI_TWO / totalFrame; int frameInterval = (int)(1000f / framerate); for (int i = 0; i < totalFrame; i++) { pipeline.Draw(entitiesApply, camera); CRenderer.Render(charBuffer); entity.Transform.Rotation.X += angleStep; entity.Transform.Rotation.Z += angleStep; Thread.Sleep(frameInterval); } }
public override Bounds Bounds(RenderEntity ent) { Bounds b = new(); b.Zero(); if (ent == null) { b.ExpandSelf(8f); } else { Vector3 target = reinterpret.cast_vec3(ent.shaderParms, IRenderWorld.SHADERPARM_BEAM_END_X); var modelMatrix = stackalloc float[16]; R_AxisToModelMatrix(ent.axis, ent.origin, modelMatrix); R_GlobalPointToLocal(modelMatrix, target, out var localTarget); b.AddPoint(localTarget); if (ent.shaderParms[IRenderWorld.SHADERPARM_BEAM_WIDTH] != 0f) { b.ExpandSelf(ent.shaderParms[IRenderWorld.SHADERPARM_BEAM_WIDTH] * 0.5f); } } return(b); }
public void AddEntity(RenderEntity Entity) { current.Add(Entity); }
public override IRenderModel InstantiateDynamicModel(RenderEntity ent, ViewDef view, IRenderModel cachedModel) { int i, surfaceNum; MD5Mesh mesh; RenderModelStatic staticModel; if (cachedModel != null && !r_useCachedDynamicModels.Bool) { cachedModel.Dispose(); cachedModel = null; } if (purged) { common.DWarning($"model {Name} instantiated while purged"); LoadModel(); } if (ent.joints == null) { common.Printf($"RenderModelMD5::InstantiateDynamicModel: null joints on renderEntity for '{Name}'\n"); cachedModel.Dispose(); return(null); } else if (ent.numJoints != joints.Length) { common.Printf($"RenderModelMD5::InstantiateDynamicModel: renderEntity has different number of joints than model for '{Name}'\n"); cachedModel.Dispose(); return(null); } tr.pc.c_generateMd5++; if (cachedModel != null) { Debug.Assert(cachedModel is RenderModelStatic); Debug.Assert(string.Equals(cachedModel.Name, MD5_SnapshotName, StringComparison.OrdinalIgnoreCase)); staticModel = (RenderModelStatic)cachedModel; } else { staticModel = new RenderModelStatic(); staticModel.InitEmpty(MD5_SnapshotName); } staticModel.bounds.Clear(); if (r_showSkel.Integer != 0) { if (view != null && (!r_skipSuppress.Bool || ent.suppressSurfaceInViewID == 0 || ent.suppressSurfaceInViewID != view.renderView.viewID)) { DrawJoints(ent, view); // only draw the skeleton } if (r_showSkel.Integer > 1) { staticModel.InitEmpty(MD5_SnapshotName); return(staticModel); } // turn off the model when showing the skeleton } // create all the surfaces for (i = 0; i < meshes.Length; i++) { mesh = meshes[i]; // avoid deforming the surface if it will be a nodraw due to a skin remapping. FIXME: may have to still deform clipping hulls var shader = mesh.shader; shader = R_RemapShaderBySkin(shader, ent.customSkin, ent.customShader); if (shader == null || (!shader.IsDrawn && !shader.SurfaceCastsShadow)) { staticModel.DeleteSurfaceWithId(i); mesh.surfaceNum = -1; continue; } ModelSurface surf; if (staticModel.FindSurfaceWithId(i, out surfaceNum)) { mesh.surfaceNum = surfaceNum; surf = staticModel.surfaces[surfaceNum]; } else { // Remove Overlays before adding new surfaces RenderModelOverlay.RemoveOverlaySurfacesFromModel(staticModel); mesh.surfaceNum = staticModel.NumSurfaces; surf = staticModel.surfaces.Alloc(); surf.geometry = null; surf.shader = null; surf.id = i; } mesh.UpdateSurface(ent, ent.joints, surf); staticModel.bounds.AddPoint(surf.geometry.bounds[0]); staticModel.bounds.AddPoint(surf.geometry.bounds[1]); } return(staticModel); }
// This calculates a rough bounds by using the joint radii without transforming all the points public override Bounds Bounds(RenderEntity ent) => ent == null ? bounds // this is the bounds for the reference pose : ent.bounds;
public void UpdateSurface(RenderEntity ent, JointMat[] joints, ModelSurface surf) { int i; tr.pc.c_deformedSurfaces++; tr.pc.c_deformedVerts += deformInfo.numOutputVerts; tr.pc.c_deformedIndexes += deformInfo.numIndexes; surf.shader = shader; if (surf.geometry != null) { // if the number of verts and indexes are the same we can re-use the triangle surface the number of indexes must be the same to assure the correct amount of memory is allocated for the facePlanes if (surf.geometry.numVerts == deformInfo.numOutputVerts && surf.geometry.numIndexes == deformInfo.numIndexes) { R_FreeStaticTriSurfVertexCaches(surf.geometry); } else { R_FreeStaticTriSurf(surf.geometry); surf.geometry = R_AllocStaticTriSurf(); } } else { surf.geometry = R_AllocStaticTriSurf(); } var tri = surf.geometry; // note that some of the data is references, and should not be freed tri.deformedSurface = true; tri.tangentsCalculated = false; tri.facePlanesCalculated = false; tri.numIndexes = deformInfo.numIndexes; tri.indexes = deformInfo.indexes; tri.silIndexes = deformInfo.silIndexes; tri.numMirroredVerts = deformInfo.numMirroredVerts; tri.mirroredVerts = deformInfo.mirroredVerts; tri.numDupVerts = deformInfo.numDupVerts; tri.dupVerts = deformInfo.dupVerts; tri.numSilEdges = deformInfo.numSilEdges; tri.silEdges = deformInfo.silEdges; tri.dominantTris = deformInfo.dominantTris; tri.numVerts = deformInfo.numOutputVerts; if (tri.verts == null) { R_AllocStaticTriSurfVerts(tri, tri.numVerts); for (i = 0; i < deformInfo.numSourceVerts; i++) { tri.verts[i].Clear(); tri.verts[i].st = texCoords[i]; } } fixed(JointMat *jointsJ = joints) if (ent.shaderParms[IRenderWorld.SHADERPARM_MD5_SKINSCALE] != 0f) { TransformScaledVerts(tri.verts, jointsJ, ent.shaderParms[IRenderWorld.SHADERPARM_MD5_SKINSCALE]); } else { TransformVerts(tri.verts, jointsJ); } // replicate the mirror seam vertexes var base_ = deformInfo.numOutputVerts - deformInfo.numMirroredVerts; for (i = 0; i < deformInfo.numMirroredVerts; i++) { tri.verts[base_ + i] = tri.verts[deformInfo.mirroredVerts[i]]; } R_BoundTriSurf(tri); // If a surface is going to be have a lighting interaction generated, it will also have to call R_DeriveTangents() to get normals, tangents, and face planes. If it only // needs shadows generated, it will only have to generate face planes. If it only has ambient drawing, or is culled, no additional work will be necessary if (!r_useDeferredTangents.Bool) { R_DeriveTangents(tri); // set face planes, vertex normals, tangents } }
public static void CreateOutput(object sender, object selectedItem) { if (selectedItem is OutputCollectionViewModel outputCollectionViewModel) { CreateOutput(sender, outputCollectionViewModel.Parent); return; } if (!(selectedItem is GroupViewModel entityGroupViewModel)) { return; } var button = (Button)sender; var type = (string)button.CommandParameter; OutputBase entity; switch (type) { case nameof(RenderArrayHint): entity = RenderArrayHint.New(); break; case nameof(RenderNextDate): entity = RenderNextDate.New("Name", "0001-01-01", "Weekly"); break; case nameof(RenderIndex): entity = RenderIndex.New(); break; case nameof(RenderEntity): entity = RenderEntity.New(); break; case nameof(RenderLink): entity = RenderLink.New(); break; case nameof(RenderProperty): entity = RenderProperty.New("Display Name", "Property Name"); break; case nameof(RenderValue): entity = RenderValue.New("Name", "Value"); break; case nameof(RenderTypeName): entity = RenderTypeName.New("Name"); break; case nameof(RenderTaxPeriodDate): entity = RenderTaxPeriodDate.New("Name", "2020", "1"); break; case nameof(RenderConstant): entity = RenderConstant.New("Name", "Constant Name", typeof(DateTime)); break; case nameof(RenderTaxPeriod): entity = RenderTaxPeriod.New("Name", "Monthly", "0001-01-01"); break; case nameof(RenderDateAdd): entity = RenderDateAdd.New("Name", "0001-01-01", "Day", "1"); break; case nameof(RenderUniqueKeyFromLink): entity = RenderUniqueKeyFromLink.New("Name", "[Link]"); break; case nameof(Avg): entity = Avg.New("Name", "Property"); break; case nameof(Max): entity = Max.New("Name", "Property"); break; case nameof(Min): entity = Min.New("Name", "Property"); break; case nameof(Sum): entity = Sum.New("Name", "Property"); break; case nameof(Count): entity = Count.New("Name"); break; case nameof(ExpressionCalculator): entity = ExpressionCalculator.New("Name", "1 + 2 - 3 * 4 / 5", rounding: RoundingOption.NotSet); break; case nameof(Distinct): entity = Distinct.New("Name", "Property"); break; default: throw new ArgumentOutOfRangeException(); } entityGroupViewModel.Element.Outputs.Add(entity); var viewModelCollection = entityGroupViewModel.Children.OfType <OutputCollectionViewModel>().First(); var viewModel = new OutputViewModel(entity, viewModelCollection); viewModelCollection.Children.Add(viewModel); entityGroupViewModel.IsExpanded = true; viewModelCollection.IsExpanded = true; viewModel.IsSelected = true; viewModel.IsExpanded = true; }
public unsafe RenderBuffer <float> Draw(RenderEntity[] entities, ICamera camera) { RenderTarget.Clear(); int entityCount = entities.Length; Fragment **rasterizedFragments = stackalloc Fragment *[entityCount]; int * primitiveCounts = stackalloc int[entityCount]; BeginRasterize(); ShaderValue.WorldToView = camera.WorldToView; ShaderValue.Time = CRenderer.CurrentSecond; ShaderValue.SinTime = MathF.Sin(ShaderValue.Time); for (int i = 0; i < entityCount; i++) { RenderEntity instanceCopy = entities[i].GetInstanceToApply(); IMaterial material = instanceCopy.Material ?? DEFAULT_MATERIAL; Vector4[] vertices = instanceCopy.Model.Vertices; IPrimitive[] primitives = instanceCopy.Model.Primitives; ShaderValue.ObjectToWorld = instanceCopy.Transform.LocalToWorld; ShaderValue.ObjectToView = ShaderValue.WorldToView * ShaderValue.ObjectToWorld; ShaderInvoker <IVertexShader> .ChangeActiveShader(material.ShaderType, material.Shader); int vertexCount = vertices.Length; Vector2 *coordsOutput = stackalloc Vector2[vertexCount]; Vector4 *vertexOutput = stackalloc Vector4[vertexCount]; for (int j = 0; j < vertexCount; j++) { ShaderInOutMap outputMap = ShaderInvoker <IVertexShader> .Invoke(j, vertices); vertexOutput[j] = *outputMap.VertexPtr; coordsOutput[j] = ViewToScreen(*outputMap.VertexPtr); } Fragment *fragments = stackalloc Fragment[primitives.Length]; primitiveCounts[i] = primitives.Length; for (int j = 0; j < primitives.Length; j++) { Rasterize(coordsOutput, primitives[j], fragments + j); } rasterizedFragments[i] = fragments; } EndRasterize(); //Octree is so annoying //TODO: View frustum clip, triangle clip, pixel clip //Clipping(); //This is not the proper way to output, just to check result as soon as possible GenericVector <float> white = new GenericVector <float>(3) { 1, 1, 1 }; for (int i = 0; i < entityCount; i++) { for (int j = 0; j < primitiveCounts[i]; j++) { RenderTarget.WritePixel(rasterizedFragments[i][j].Rasterization, rasterizedFragments[i][j].PixelCount, white); } } return(RenderTarget); }
public override IRenderModel InstantiateDynamicModel(RenderEntity ent, ViewDef view, IRenderModel cachedModel) { idRenderModelStatic *staticModel; if (cachedModel && !r_useCachedDynamicModels.GetBool()) { delete cachedModel; cachedModel = NULL; } // this may be triggered by a model trace or other non-view related source, to which we should look like an empty model if (renderEntity == NULL || viewDef == NULL) { delete cachedModel; return(NULL); } if (r_skipParticles.GetBool()) { delete cachedModel; return(NULL); } /* * // if the entire system has faded out * if ( renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] && viewDef->renderView.time * 0.001f >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] ) { * delete cachedModel; * return NULL; * } */ if (cachedModel != NULL) { assert(dynamic_cast <idRenderModelStatic *>(cachedModel) != NULL); assert(idStr::Icmp(cachedModel->Name(), parametricParticle_SnapshotName) == 0); staticModel = static_cast <idRenderModelStatic *>(cachedModel); } else { staticModel = new idRenderModelStatic; staticModel->InitEmpty(parametricParticle_SnapshotName); } particleGen_t g; g.renderEnt = renderEntity; g.renderView = &viewDef->renderView; g.origin.Zero(); g.axis.Identity(); for (int stageNum = 0; stageNum < particleSystem->stages.Num(); stageNum++) { idParticleStage *stage = particleSystem->stages[stageNum]; if (!stage->material) { continue; } if (!stage->cycleMsec) { continue; } if (stage->hidden) { // just for gui particle editor use staticModel->DeleteSurfaceWithId(stageNum); continue; } idRandom steppingRandom, steppingRandom2; int stageAge = g.renderView->time + renderEntity->shaderParms[SHADERPARM_TIMEOFFSET] * 1000 - stage->timeOffset * 1000; int stageCycle = stageAge / stage->cycleMsec; // some particles will be in this cycle, some will be in the previous cycle steppingRandom.SetSeed(((stageCycle << 10) & idRandom::MAX_RAND) ^ (int)(renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND)); steppingRandom2.SetSeed((((stageCycle - 1) << 10) & idRandom::MAX_RAND) ^ (int)(renderEntity->shaderParms[SHADERPARM_DIVERSITY] * idRandom::MAX_RAND)); int count = stage->totalParticles * stage->NumQuadsPerParticle(); int surfaceNum; modelSurface_t *surf; if (staticModel->FindSurfaceWithId(stageNum, surfaceNum)) { surf = &staticModel->surfaces[surfaceNum]; R_FreeStaticTriSurfVertexCaches(surf->geometry); } else { surf = &staticModel->surfaces.Alloc(); surf->id = stageNum; surf->shader = stage->material; surf->geometry = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts(surf->geometry, 4 * count); R_AllocStaticTriSurfIndexes(surf->geometry, 6 * count); R_AllocStaticTriSurfPlanes(surf->geometry, 6 * count); } int numVerts = 0; idDrawVert *verts = surf->geometry->verts; for (int index = 0; index < stage->totalParticles; index++) { g.index = index; // bump the random steppingRandom.RandomInt(); steppingRandom2.RandomInt(); // calculate local age for this index int bunchOffset = stage->particleLife * 1000 * stage->spawnBunching * index / stage->totalParticles; int particleAge = stageAge - bunchOffset; int particleCycle = particleAge / stage->cycleMsec; if (particleCycle < 0) { // before the particleSystem spawned continue; } if (stage->cycles && particleCycle >= stage->cycles) { // cycled systems will only run cycle times continue; } if (particleCycle == stageCycle) { g.random = steppingRandom; } else { g.random = steppingRandom2; } int inCycleTime = particleAge - particleCycle * stage->cycleMsec; if (renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] && g.renderView->time - inCycleTime >= renderEntity->shaderParms[SHADERPARM_PARTICLE_STOPTIME] * 1000) { // don't fire any more particles continue; } // supress particles before or after the age clamp g.frac = (float)inCycleTime / (stage->particleLife * 1000); if (g.frac < 0.0f) { // yet to be spawned continue; } if (g.frac > 1.0f) { // this particle is in the deadTime band continue; } // this is needed so aimed particles can calculate origins at different times g.originalRandom = g.random; g.age = g.frac * stage->particleLife; // if the particle doesn't get drawn because it is faded out or beyond a kill region, don't increment the verts numVerts += stage->CreateParticle(&g, verts + numVerts); } // numVerts must be a multiple of 4 assert((numVerts & 3) == 0 && numVerts <= 4 * count); // build the indexes int numIndexes = 0; glIndex_t *indexes = surf->geometry->indexes; for (int i = 0; i < numVerts; i += 4) { indexes[numIndexes + 0] = i; indexes[numIndexes + 1] = i + 2; indexes[numIndexes + 2] = i + 3; indexes[numIndexes + 3] = i; indexes[numIndexes + 4] = i + 3; indexes[numIndexes + 5] = i + 1; numIndexes += 6; } surf->geometry->tangentsCalculated = false; surf->geometry->facePlanesCalculated = false; surf->geometry->numVerts = numVerts; surf->geometry->numIndexes = numIndexes; surf->geometry->bounds = stage->bounds; // just always draw the particles } return(staticModel); }
public override Bounds Bounds(RenderEntity ent) => particleSystem.bounds;
=> true; // don't ever need to load public override IRenderModel InstantiateDynamicModel(RenderEntity ent, ViewDef view, IRenderModel cachedModel) { RenderModelStatic staticModel; SrfTriangles tri; ModelSurface surf; if (cachedModel != null) { cachedModel = null; } if (ent == null || view == null) { return(null); } if (cachedModel != null) { Debug.Assert(cachedModel is RenderModelStatic); Debug.Assert(string.Equals(cachedModel.Name, beam_SnapshotName, StringComparison.OrdinalIgnoreCase)); staticModel = (RenderModelStatic)cachedModel; surf = staticModel.Surface(0); tri = surf.geometry; } else { staticModel = new RenderModelStatic(); staticModel.InitEmpty(beam_SnapshotName); tri = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts(tri, 4); R_AllocStaticTriSurfIndexes(tri, 6); tri.verts[0].Clear(); tri.verts[0].st.x = 0; tri.verts[0].st.y = 0; tri.verts[1].Clear(); tri.verts[1].st.x = 0; tri.verts[1].st.y = 1; tri.verts[2].Clear(); tri.verts[2].st.x = 1; tri.verts[2].st.y = 0; tri.verts[3].Clear(); tri.verts[3].st.x = 1; tri.verts[3].st.y = 1; tri.indexes[0] = 0; tri.indexes[1] = 2; tri.indexes[2] = 1; tri.indexes[3] = 2; tri.indexes[4] = 3; tri.indexes[5] = 1; tri.numVerts = 4; tri.numIndexes = 6; surf = new(); surf.geometry = tri; surf.id = 0; surf.shader = tr.defaultMaterial; staticModel.AddSurface(surf); } Vector3 target = reinterpret.cast_vec3(ent.shaderParms, IRenderWorld.SHADERPARM_BEAM_END_X); // we need the view direction to project the minor axis of the tube as the view changes var modelMatrix = stackalloc float[16]; R_AxisToModelMatrix(ent.axis, ent.origin, modelMatrix); R_GlobalPointToLocal(modelMatrix, view.renderView.vieworg, out var localView); R_GlobalPointToLocal(modelMatrix, target, out var localTarget); Vector3 major = localTarget; Vector3 minor = default; Vector3 mid = 0.5f * localTarget; Vector3 dir = mid - localView; minor.Cross(major, dir); minor.Normalize(); if (ent.shaderParms[IRenderWorld.SHADERPARM_BEAM_WIDTH] != 0f) { minor *= ent.shaderParms[IRenderWorld.SHADERPARM_BEAM_WIDTH] * 0.5f; } var red = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_RED] * 255f); var green = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_GREEN] * 255f); var blue = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_BLUE] * 255f); var alpha = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_ALPHA] * 255f); tri.verts[0].xyz = minor; tri.verts[0].color0 = red; tri.verts[0].color1 = green; tri.verts[0].color2 = blue; tri.verts[0].color3 = alpha; tri.verts[1].xyz = -minor; tri.verts[1].color0 = red; tri.verts[1].color1 = green; tri.verts[1].color2 = blue; tri.verts[1].color3 = alpha; tri.verts[2].xyz = localTarget + minor; tri.verts[2].color0 = red; tri.verts[2].color1 = green; tri.verts[2].color2 = blue; tri.verts[2].color3 = alpha; tri.verts[3].xyz = localTarget - minor; tri.verts[3].color0 = red; tri.verts[3].color1 = green; tri.verts[3].color2 = blue; tri.verts[3].color3 = alpha; R_BoundTriSurf(tri); staticModel.bounds = tri.bounds; return(staticModel); }
public override IRenderModel InstantiateDynamicModel(RenderEntity ent, ViewDef view, IRenderModel cachedModel) { RenderModelStatic staticModel; SrfTriangles tri; ModelSurface surf; if (cachedModel != null && !r_useCachedDynamicModels.Bool) { cachedModel.Dispose(); cachedModel = null; } if (ent == null || view == null) { cachedModel.Dispose(); cachedModel = null; } if (cachedModel != null) { Debug.Assert(cachedModel is RenderModelStatic); Debug.Assert(string.Equals(cachedModel.Name, sprite_SnapshotName, StringComparison.OrdinalIgnoreCase)); staticModel = (RenderModelStatic)cachedModel; surf = staticModel.Surface(0); tri = surf.geometry; } else { staticModel = new RenderModelStatic(); staticModel.InitEmpty(sprite_SnapshotName); tri = R_AllocStaticTriSurf(); R_AllocStaticTriSurfVerts(tri, 4); R_AllocStaticTriSurfIndexes(tri, 6); tri.verts[0].Clear(); tri.verts[0].normal.Set(1f, 0f, 0f); tri.verts[0].tangents0.Set(0f, 1f, 0f); tri.verts[0].tangents1.Set(0f, 0f, 1f); tri.verts[0].st.x = 0f; tri.verts[0].st.y = 0f; tri.verts[1].Clear(); tri.verts[1].normal.Set(1f, 0f, 0f); tri.verts[1].tangents0.Set(0f, 1f, 0f); tri.verts[1].tangents1.Set(0f, 0f, 1f); tri.verts[1].st.x = 1f; tri.verts[1].st.y = 0f; tri.verts[2].Clear(); tri.verts[2].normal.Set(1f, 0f, 0f); tri.verts[2].tangents0.Set(0f, 1f, 0f); tri.verts[2].tangents1.Set(0f, 0f, 1f); tri.verts[2].st.x = 1f; tri.verts[2].st.y = 1f; tri.verts[3].Clear(); tri.verts[3].normal.Set(1f, 0f, 0f); tri.verts[3].tangents0.Set(0f, 1f, 0f); tri.verts[3].tangents1.Set(0f, 0f, 1f); tri.verts[3].st.x = 0f; tri.verts[3].st.y = 1f; tri.indexes[0] = 0; tri.indexes[1] = 1; tri.indexes[2] = 3; tri.indexes[3] = 1; tri.indexes[4] = 2; tri.indexes[5] = 3; tri.numVerts = 4; tri.numIndexes = 6; surf = new(); surf.geometry = tri; surf.id = 0; surf.shader = tr.defaultMaterial; staticModel.AddSurface(surf); } var red = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_RED] * 255f); var green = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_GREEN] * 255f); var blue = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_BLUE] * 255f); var alpha = (byte)MathX.FtoiFast(ent.shaderParms[IRenderWorld.SHADERPARM_ALPHA] * 255f); var right = new Vector3(0f, ent.shaderParms[IRenderWorld.SHADERPARM_SPRITE_WIDTH] * 0.5f, 0f); var up = new Vector3(0f, 0f, ent.shaderParms[IRenderWorld.SHADERPARM_SPRITE_HEIGHT] * 0.5f); tri.verts[0].xyz = up + right; tri.verts[0].color0 = red; tri.verts[0].color1 = green; tri.verts[0].color2 = blue; tri.verts[0].color3 = alpha; tri.verts[1].xyz = up - right; tri.verts[1].color0 = red; tri.verts[1].color1 = green; tri.verts[1].color2 = blue; tri.verts[1].color3 = alpha; tri.verts[2].xyz = -right - up; tri.verts[2].color0 = red; tri.verts[2].color1 = green; tri.verts[2].color2 = blue; tri.verts[2].color3 = alpha; tri.verts[3].xyz = right - up; tri.verts[3].color0 = red; tri.verts[3].color1 = green; tri.verts[3].color2 = blue; tri.verts[3].color3 = alpha; R_BoundTriSurf(tri); staticModel.bounds = tri.bounds; return(staticModel); }
public unsafe RenderBuffer <float> Draw <T>(RenderEntity[] entities, T camera) where T : ICamera { Clear(); int entityCount = entities.Length; BeginRasterize(); SetPerRenderValues(camera); for (int i = 0; i < entityCount; i++) { RenderEntity currentEntity = entities[i]; SetPerObjectValues(currentEntity); Material material = currentEntity.Material ?? DEFAULT_MATERIAL; Model model = currentEntity.Model; #region Vertex Stage //Prepare vertex shader VertexInvoker.ChangeActiveShader(material.ShaderType, material.Shader); //Invoke vertex shader int vertexCount = model.Vertices.Length; Vector2 *coordsOutput = stackalloc Vector2[vertexCount]; ShaderInOutPatternDefault *inoutPtr = stackalloc ShaderInOutPatternDefault[1]; for (int j = 0; j < vertexCount; j++) { VertexInvoker.Invoke(model.ReadVerticesDataAsPattern(j)); VertexInvoker.ActiveOutputMap.Write(inoutPtr); coordsOutput[j] = *(Vector2 *)&inoutPtr->Vertex; } #endregion #region Fragment Stage FragmentInvoker.ChangeActiveShader(material.ShaderType, material.Shader); //Primitive assemble int newPrimitiveCount = AssemblePrimitive(model, coordsOutput); _rasterizedFragments.AddEmpty(newPrimitiveCount); switch (_assembleMode) { case PrimitiveAssembleMode.Line: case PrimitiveAssembleMode.LineTriangle: Rasterize <LinePrimitive, Line>(_linePrimitives.GetPointer(_linePrimitives.Count - newPrimitiveCount), newPrimitiveCount, _rasterizedFragments.GetPointer(_rasterizedFragments.Count - newPrimitiveCount)); break; case PrimitiveAssembleMode.Triangle: Rasterize <TrianglePrimitive, Triangle>(_trianglePrimitives.GetPointer(_trianglePrimitives.Count - newPrimitiveCount), newPrimitiveCount, _rasterizedFragments.GetPointer(_rasterizedFragments.Count - newPrimitiveCount)); break; } for (int j = _rasterizedFragments.Count - newPrimitiveCount; j < _rasterizedFragments.Count; j++) { Fragment *fragment = _rasterizedFragments.GetPointer(j); for (int k = 0; k < fragment->PixelCount; k++) { //Fragment.FragmentData has been tailored to a proper size FragmentInvoker.Invoke((byte *)fragment->FragmentData[k]); FragmentInvoker.ActiveOutputMap.Write(inoutPtr); _renderedColors.Add(inoutPtr->Color); } fragment->FragmentColor = _renderedColors.ArchivePointer(); } #endregion } EndRasterize(); //Octree is so annoying //TODO: View frustum clip, triangle clip, pixel clip //Clipping(); //This is not the proper way to output, rather for debugging for (int i = 0; i < _rasterizedFragments.Count; i++) { Fragment *fragmentPtr = _rasterizedFragments.GetPointer(i); RenderTarget.WritePixel(fragmentPtr->Rasterization, fragmentPtr->PixelCount, fragmentPtr->FragmentColor); } return(RenderTarget); }