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); }
private idScreenRect ScreenRectangleFromWinding(idWinding winding, ViewEntity space) { idScreenRect rect = new idScreenRect(); Vector3 v, ndc; View viewDef = idE.RenderSystem.ViewDefinition; for(int i = 0; i < winding.PointCount; i++) { idHelper.LocalPointToGlobal(space.ModelMatrix, winding[i], out v); idHelper.GlobalToNormalizedDeviceCoordinates(v, out ndc); float windowX = 0.5f * (1.0f + ndc.X) * (viewDef.ViewPort.X2 - viewDef.ViewPort.X1); float windowY = 0.5f * (1.0f + ndc.Y) * (viewDef.ViewPort.Y2 - viewDef.ViewPort.Y1); rect.AddPoint(windowX, windowY); } rect.Expand(); return rect; }
/// <summary> /// If the entityDef isn't already on the viewEntity list, create /// a viewEntity and add it to the list with an empty scissor rect. /// </summary> /// <remarks> /// This does not instantiate dynamic models for the entity yet. /// </remarks> /// <param name="def"></param> /// <returns></returns> private ViewEntity SetEntityDefViewEntity(idRenderEntity def) { if(def.ViewCount == idE.RenderSystem.ViewCount) { return def.ViewEntity; } def.ViewCount = idE.RenderSystem.ViewCount; // set the model and modelview matricies ViewEntity viewModel = new ViewEntity(); viewModel.EntityDef = def; // the scissorRect will be expanded as the model bounds is accepted into visible portal chains viewModel.ScissorRectangle.Clear(); // copy the model and weapon depth hack for back-end use viewModel.ModelDepthHack = def.Parameters.ModelDepthHack; viewModel.WeaponDepthHack = def.Parameters.WeaponDepthHack; viewModel.ModelMatrix = idHelper.AxisToModelMatrix(def.Parameters.Axis, def.Parameters.Origin); // we may not have a viewDef if we are just creating shadows at entity creation time if(idE.RenderSystem.ViewDefinition != null) { idHelper.ConvertMatrix(viewModel.ModelMatrix, idE.RenderSystem.ViewDefinition.WorldSpace.ModelViewMatrix, out viewModel.ModelViewMatrix); idE.RenderSystem.ViewDefinition.ViewEntities = new List<ViewEntity>(); idE.RenderSystem.ViewDefinition.ViewEntities.Add(viewModel); } def.ViewEntity = viewModel; return viewModel; }
public void Init() { idConsole.WriteLine("------- Initializing renderSystem --------"); // clear all our internal state _viewCount = 1; // so cleared structures never match viewCount // we used to memset tr, but now that it is a class, we can't, so // there may be other state we need to reset _ambientLightVector = new Vector4(0.5f, 0.5f - 0.385f, 0.8925f, 1.0f); _frameData.Commands = new Queue<RenderCommand>(); _backendRenderer = new Backends.XNARenderBackend(); InitCommands(); InitRenderer(); _guiModel = new idGuiModel(); _demoGuiModel = new idGuiModel(); // TODO: R_InitTriSurfData(); idE.ImageManager.Init(); // TODO: idCinematic::InitCinematic( ); // build brightness translation tables SetColorMappings(); InitMaterials(); idE.RenderModelManager.Init(); // set the identity space _identitySpace = new ViewEntity(); idConsole.WriteLine("renderSystem initialized."); idConsole.WriteLine("--------------------------------------"); }
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 void SetViewMatrix(View view) { float[] viewerMatrix = new float[16]; ViewEntity world = new ViewEntity(); // transform by the camera placement Vector3 origin = view.RenderView.ViewOrigin; /*viewerMatrix[0] = _viewDefinition.RenderView.ViewAxis.M11; viewerMatrix[4] = _viewDefinition.RenderView.ViewAxis.M12; viewerMatrix[8] = _viewDefinition.RenderView.ViewAxis.M13; viewerMatrix[12] = -origin.X * viewerMatrix[0] + -origin.Y * viewerMatrix[4] + -origin.Z * viewerMatrix[8]; viewerMatrix[1] = _viewDefinition.RenderView.ViewAxis.M21; viewerMatrix[5] = _viewDefinition.RenderView.ViewAxis.M22; viewerMatrix[9] = _viewDefinition.RenderView.ViewAxis.M23; viewerMatrix[13] = -origin.X * viewerMatrix[1] + -origin.Y * viewerMatrix[5] + -origin.Z * viewerMatrix[9]; viewerMatrix[2] = _viewDefinition.RenderView.ViewAxis.M31; viewerMatrix[6] = _viewDefinition.RenderView.ViewAxis.M32; viewerMatrix[10] = _viewDefinition.RenderView.ViewAxis.M33; viewerMatrix[14] = -origin.X * viewerMatrix[2] + -origin.Y * viewerMatrix[6] + -origin.Z * viewerMatrix[10]; viewerMatrix[3] = 0; viewerMatrix[7] = 0; viewerMatrix[11] = 0; viewerMatrix[15] = 1;*/ Vector3 look = origin + Vector3.Transform(Vector3.Forward, _viewDefinition.RenderView.ViewAxis); world.ModelViewMatrix = Matrix.CreateLookAt(origin, look, Vector3.Up); //world.ModelViewMatrix = Matrix.Multiply(world.ModelViewMatrix, FlipMatrix); view.WorldSpace = world; // convert from our coordinate system (looking down X) // to OpenGL's coordinate system (looking down -Z) //idHelper.ConvertMatrix(viewerMatrix, FlipMatrix, out view.WorldSpace.ModelViewMatrix); }
private void Clear() { _frameCount = 0; _viewCount = 0; _staticAllocCount = 0; _frameShaderTime = 0; _viewPortOffset = Vector2.Zero; _tiledViewPort = Vector2.Zero; _ambientLightVector = Vector4.Zero; _sortOffset = 0; _worlds.Clear(); _primaryRenderWorld = null; _primaryView = null; _primaryRenderView = new idRenderView(); _defaultMaterial = null; /* testImage = NULL; ambientCubeImage = NULL;*/ _viewDefinition = null; /*memset( &pc, 0, sizeof( pc ) ); memset( &lockSurfacesCmd, 0, sizeof( lockSurfacesCmd ) );*/ _identitySpace = new ViewEntity(); /*logFile = NULL;*/ _renderCrops = new idRectangle[idE.MaxRenderCrops]; _currentRenderCrop = 0; _guiRecursionLevel = 0; _guiModel = null; /*demoGuiModel = NULL; memset( gammaTable, 0, sizeof( gammaTable ) ); takingScreenshot = false;*/ }
/// <summary> /// Adds surfaces for the given viewEntity /// Walks through the viewEntitys list and creates drawSurf_t for each surface of /// each viewEntity that has a non-empty scissorRect. /// </summary> /// <param name="viewEntity"></param> private void AddAmbientDrawSurfaces(ViewEntity viewEntity) { idRenderEntity def = viewEntity.EntityDef; idRenderModel model; idMaterial material; Surface geometry; if(def.DynamicModel != null) { model = def.DynamicModel; } else { model = def.Parameters.Model; } // add all the surfaces int total = model.SurfaceCount; for(int i = 0; i < total; i++) { RenderModelSurface surface = model.GetSurface(i); // for debugging, only show a single surface at a time if((idE.CvarSystem.GetInteger("r_singleSurface") >= 0) && (i != idE.CvarSystem.GetInteger("r_singleSurface"))) { continue; } geometry = surface.Geometry; if(geometry == null) { continue; } else if(geometry.Indexes.Length == 0) { continue; } material = surface.Material; material = RemapMaterialBySkin(material, def.Parameters.CustomSkin, def.Parameters.CustomMaterial); material = GlobalMaterialOverride(material); if(material == null) { continue; } else if(material.IsDrawn == false) { continue; } // debugging tool to make sure we are have the correct pre-calculated bounds if(idE.CvarSystem.GetBool("r_checkBounds") == true) { idConsole.Warning("TODO: r_checkBounds"); /*int j, k; for ( j = 0 ; j < tri->numVerts ; j++ ) { for ( k = 0 ; k < 3 ; k++ ) { if ( tri->verts[j].xyz[k] > tri->bounds[1][k] + CHECK_BOUNDS_EPSILON || tri->verts[j].xyz[k] < tri->bounds[0][k] - CHECK_BOUNDS_EPSILON ) { common->Printf( "bad tri->bounds on %s:%s\n", def->parms.hModel->Name(), shader->GetName() ); break; } if ( tri->verts[j].xyz[k] > def->referenceBounds[1][k] + CHECK_BOUNDS_EPSILON || tri->verts[j].xyz[k] < def->referenceBounds[0][k] - CHECK_BOUNDS_EPSILON ) { common->Printf( "bad referenceBounds on %s:%s\n", def->parms.hModel->Name(), shader->GetName() ); break; } } if ( k != 3 ) { break; } }*/ } // TODO: CullLocalBox // if ( !R_CullLocalBox( tri->bounds, vEntity->modelMatrix, 5, tr.viewDef->frustum ) ) { { def.ViewCount = this.ViewCount; // make sure we have an ambient cache if(CreateAmbientCache(geometry, /* TODO: shader->ReceivesLighting() */ false) == false) { // don't add anything if the vertex cache was too full to give us an ambient cache return; } // touch it so it won't get purged //vertexCache.Touch( tri->ambientCache ); /*if ( r_useIndexBuffers.GetBool() && !tri->indexCache ) { vertexCache.Alloc( tri->indexes, tri->numIndexes * sizeof( tri->indexes[0] ), &tri->indexCache, true ); } if ( tri->indexCache ) { vertexCache.Touch( tri->indexCache ); }*/ // add the surface for drawing AddDrawSurface(geometry, viewEntity, viewEntity.EntityDef.Parameters, material, viewEntity.ScissorRectangle); // ambientViewCount is used to allow light interactions to be rejected // if the ambient surface isn't visible at all geometry.AmbientViewCount = this.ViewCount; } } // add the lightweight decal surfaces // TODO: decals /*for ( idRenderModelDecal *decal = def->decals; decal; decal = decal->Next() ) { decal->AddDecalDrawSurf( vEntity ); }*/ }