private void AddCubeFace(Surface tri, int faceNumber, Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4) { int verticeOffset = faceNumber * 4; int indexOffset = faceNumber * 6; tri.Vertices[verticeOffset + 0].Clear(); tri.Vertices[verticeOffset + 0].Position = v1 * 8; tri.Vertices[verticeOffset + 0].TextureCoordinates = new Vector2(0, 0); tri.Vertices[verticeOffset + 1].Clear(); tri.Vertices[verticeOffset + 1].Position = v2 * 8; tri.Vertices[verticeOffset + 1].TextureCoordinates = new Vector2(1, 0); tri.Vertices[verticeOffset + 2].Clear(); tri.Vertices[verticeOffset + 2].Position = v3 * 8; tri.Vertices[verticeOffset + 2].TextureCoordinates = new Vector2(1, 1); tri.Vertices[verticeOffset + 3].Clear(); tri.Vertices[verticeOffset + 3].Position = v4 * 8; tri.Vertices[verticeOffset + 3].TextureCoordinates = new Vector2(0, 1); tri.Indexes[indexOffset + 0] = verticeOffset + 0; tri.Indexes[indexOffset + 1] = verticeOffset + 1; tri.Indexes[indexOffset + 2] = verticeOffset + 2; tri.Indexes[indexOffset + 3] = verticeOffset + 0; tri.Indexes[indexOffset + 4] = verticeOffset + 2; tri.Indexes[indexOffset + 5] = verticeOffset + 3; }
private void EmitSurface(GuiModelSurface surface, Matrix modelMatrix, Matrix modelViewMatrix, bool depthHack) { if(surface.VertexCount == 0) { // nothing in the surface return; } // copy verts and indexes Surface tri = new Surface(); tri.Indexes = new int[surface.IndexCount]; tri.Vertices = new Vertex[surface.VertexCount]; _indexes.CopyTo(surface.FirstIndex, tri.Indexes, 0, surface.IndexCount); // we might be able to avoid copying these and just let them reference the list vars // but some things, like deforms and recursive // guis, need to access the verts in cpu space, not just through the vertex range _vertices.CopyTo(surface.FirstVertex, tri.Vertices, 0, surface.VertexCount); // move the verts to the vertex cache tri.AmbientCache = idE.RenderSystem.AllocateVertexCacheFrameTemporary(tri.Vertices); // if we are out of vertex cache, don't create the surface if(tri.AmbientCache == null) { return; } RenderEntityComponent renderEntity = new RenderEntityComponent(); renderEntity.MaterialParameters[0] = surface.Color.X; renderEntity.MaterialParameters[1] = surface.Color.Y; renderEntity.MaterialParameters[2] = surface.Color.Z; renderEntity.MaterialParameters[3] = surface.Color.W; ViewEntity guiSpace = new ViewEntity(); guiSpace.ModelMatrix = modelMatrix; guiSpace.ModelViewMatrix = modelViewMatrix; guiSpace.WeaponDepthHack = depthHack; // add the surface, which might recursively create another gui idE.RenderSystem.AddDrawSurface(tri, guiSpace, renderEntity, surface.Material, idE.RenderSystem.ViewDefinition.Scissor); }
public void AddDrawSurface(Surface surface, ViewEntity space, RenderEntityComponent renderEntity, idMaterial material, idScreenRect scissor) { float[] materialParameters; float[] referenceRegisters = new float[idE.MaxExpressionRegisters]; float[] generatedMaterialParameters = new float[idE.MaxEntityMaterialParameters]; DrawSurface drawSurface = new DrawSurface(); drawSurface.Geometry = surface; drawSurface.Space = space; drawSurface.Material = material; drawSurface.ScissorRectangle = scissor; drawSurface.Sort = (float) material.Sort + _sortOffset; // bumping this offset each time causes surfaces with equal sort orders to still // deterministically draw in the order they are added _sortOffset += 0.000001f; // process the shader expressions for conditionals / color / texcoords float[] constantRegisters = material.ConstantRegisters; if(constantRegisters != null) { // shader only uses constant values drawSurface.MaterialRegisters = constantRegisters; } else { drawSurface.MaterialRegisters = new float[material.RegisterCount]; // a reference shader will take the calculated stage color value from another shader // and use that for the parm0-parm3 of the current shader, which allows a stage of // a light model and light flares to pick up different flashing tables from // different light shaders if(renderEntity.ReferenceMaterial != null) { // evaluate the reference shader to find our shader parms //renderEntity.ReferenceMaterial.EvaluateRegisters(ref referenceRegisters, renderEntity.MaterialParameters, this.ViewDefinition, renderEntity.ReferenceSound); idConsole.Warning("TODO: ref material"); /*MaterialStage stage = renderEntity.ReferenceMaterial.GetStage(0); memcpy( generatedShaderParms, renderEntity->shaderParms, sizeof( generatedShaderParms ) ); generatedShaderParms[0] = refRegs[ pStage->color.registers[0] ]; generatedShaderParms[1] = refRegs[ pStage->color.registers[1] ]; generatedShaderParms[2] = refRegs[ pStage->color.registers[2] ];*/ materialParameters = generatedMaterialParameters; } else { // evaluate with the entityDef's shader parms materialParameters = renderEntity.MaterialParameters; } float oldFloatTime = 0; int oldTime = 0; if((space.EntityDef != null) && (space.EntityDef.Parameters.TimeGroup != 0)) { oldFloatTime = this.ViewDefinition.FloatTime; oldTime = this.ViewDefinition.RenderView.Time; this.ViewDefinition.FloatTime = idE.Game.GetTimeGroupTime(space.EntityDef.Parameters.TimeGroup) * 0.001f; this.ViewDefinition.RenderView.Time = idE.Game.GetTimeGroupTime(space.EntityDef.Parameters.TimeGroup); } material.EvaluateRegisters(ref drawSurface.MaterialRegisters, materialParameters, idE.RenderSystem.ViewDefinition /* TODO: ,renderEntity->referenceSound*/); if((space.EntityDef != null) && (space.EntityDef.Parameters.TimeGroup != 0)) { this.ViewDefinition.FloatTime = oldFloatTime; this.ViewDefinition.RenderView.Time = oldTime; } } // check for deformations // TODO: R_DeformDrawSurf( drawSurf ); // skybox surfaces need a dynamic texgen // TODO: skybox /*switch( shader->Texgen() ) { case TG_SKYBOX_CUBE: R_SkyboxTexGen( drawSurf, tr.viewDef->renderView.vieworg ); break; case TG_WOBBLESKY_CUBE: R_WobbleskyTexGen( drawSurf, tr.viewDef->renderView.vieworg ); break; }*/ // check for gui surfaces // TODO: gui surface idUserInterface gui = null; if(space.EntityDef == null) { gui = material.GlobalInterface; } else { idConsole.Warning("TODO: global gui"); /*int guiNum = shader->GetEntityGui() - 1; if ( guiNum >= 0 && guiNum < MAX_RENDERENTITY_GUI ) { gui = renderEntity->gui[ guiNum ]; } if ( gui == NULL ) { gui = shader->GlobalGui(); }*/ } if(gui != null) { // force guis on the fast time float oldFloatTime = this.ViewDefinition.FloatTime; int oldTime = this.ViewDefinition.RenderView.Time; this.ViewDefinition.FloatTime = idE.Game.GetTimeGroupTime(1) * 0.001f; this.ViewDefinition.RenderView.Time = idE.Game.GetTimeGroupTime(1); idBounds ndcBounds; idConsole.Warning("TODO: precise cull + render gui surface"); /*if ( !R_PreciseCullSurface( drawSurf, ndcBounds ) ) { // did we ever use this to forward an entity color to a gui that didn't set color? // memcpy( tr.guiShaderParms, shaderParms, sizeof( tr.guiShaderParms ) ); R_RenderGuiSurf( gui, drawSurf ); }*/ this.ViewDefinition.FloatTime = oldFloatTime; this.ViewDefinition.RenderView.Time = oldTime; } _viewDefinition.DrawSurfaces.Add(drawSurface); // we can't add subviews at this point, because that would // increment tr.viewCount, messing up the rest of the surface // adds for this view }
private bool CreateAmbientCache(Surface geometry, bool needsLighting) { if(geometry.AmbientCache != null) { return true; } // we are going to use it for drawing, so make sure we have the tangents and normals // TODO: lighting /*if ( needsLighting && !tri->tangentsCalculated ) { R_DeriveTangents( tri ); }*/ geometry.AmbientCache = new VertexCache(); geometry.AmbientCache.Data = geometry.Vertices; return true; }