private void RenderMaterialPasses(DrawSurface surface) { Surface tri = surface.Geometry; idMaterial material = surface.Material; int count; if(material.HasAmbient == false) { // disabled because we don't do lighting right now //TODO: return; } if(material.IsPortalSky == true) { return; } // change the matrix if needed if(surface.Space != _currentSpace) { _effect.View = surface.Space.ModelViewMatrix; _currentSpace = surface.Space; //idConsole.Warning("TODO: RB_SetProgramEnvironmentSpace();"); } // change the scissor if needed if((idE.CvarSystem.GetBool("r_useScissor") == true) && (_currentScissor != surface.ScissorRectangle)) { _currentScissor = surface.ScissorRectangle; _graphicsDevice.ScissorRectangle = new Rectangle( _viewDef.ViewPort.X1 + _currentScissor.X1, _viewDef.ViewPort.Y1 + _currentScissor.Y1, _currentScissor.X2 + 1 - _currentScissor.X1, _currentScissor.Y2 + 1 - _currentScissor.Y1); } // some deforms may disable themselves by setting numIndexes = 0 if(tri.Indexes.Length == 0) { return; } if(tri.AmbientCache == null) { idConsole.WriteLine("RenderShaderPasses: !tri.AmbientCache"); return; } // get the expressions for conditionals / color / texcoords float[] registers = surface.MaterialRegisters; // set face culling appropriately SetCull(material.CullType); // set polygon offset if necessary if(material.TestMaterialFlag(MaterialFlags.PolygonOffset) == true) { idConsole.Warning("TODO: polygon offset fill"); //Gl.glEnable(Gl.GL_POLYGON_OFFSET_FILL); //Gl.glPolygonOffset(idE.CvarSystem.GetFloat("r_offsetFactor"), idE.CvarSystem.GetFloat("r_offsetUnits") * material.PolygonOffset); } if(surface.Space.WeaponDepthHack == true) { idConsole.Warning("TODO: RB_EnterWeaponDepthHack();"); } if(surface.Space.ModelDepthHack != 0.0f) { idConsole.Warning("TODO: RB_EnterModelDepthHack( surf->space->modelDepthHack );"); } foreach(MaterialStage stage in material.Stages) { // check the enable condition if(registers[stage.ConditionRegister] == 0) { continue; } // skip the stages involved in lighting if(stage.Lighting != StageLighting.Ambient) { // disabled because we don't do lighting right now // TODO: continue; } // skip if the stage is ( GL_ZERO, GL_ONE ), which is used for some alpha masks if((stage.DrawStateBits & (MaterialStates.SourceBlendBits | MaterialStates.DestinationBlendBits)) == (MaterialStates.SourceBlendZero | MaterialStates.DestinationBlendOne)) { continue; } // see if we are a new-style stage NewMaterialStage newStage = stage.NewStage; if(newStage.IsEmpty == false) { throw new Exception("THIS MIGHT NOT WORK!!!"); //-------------------------- // // new style stages // //-------------------------- if(idE.CvarSystem.GetBool("r_skipNewAmbient") == true) { continue; } idConsole.Warning("TODO: render"); /*Gl.glColorPointer(4, Gl.GL_UNSIGNED_BYTE, Marshal.SizeOf(typeof(Vertex)), (void*) &ambientCacheData->color); Gl.glVertexAttribPointerARB(9, 3, Gl.GL_FLOAT, false, Marshal.SizeOf(typeof(Vertex)), ambientCacheData->tangents[0].ToFloatPtr()); Gl.glVertexAttribPointerARB(10, 3, Gl.GL_FLOAT, false, Marshal.SizeOf(typeof(Vertex)), ambientCacheData->tangents[1].ToFloatPtr()); Gl.glNormalPointer(Gl.GL_FLOAT, Marshal.SizeOf(typeof(Vertex)), ambientCacheData->normal.ToFloatPtr());*/ //Gl.glEnableClientState(Gl.GL_COLOR_ARRAY); //Gl.glEnableVertexAttribArray(9); //Gl.glEnableVertexAttribArray(10); //Gl.glEnableClientState(Gl.GL_NORMAL_ARRAY); SetState(stage.DrawStateBits); idConsole.Warning("TODO: glBindProgramARB"); /*Gl.glBindProgramARB(Gl.GL_VERTEX_PROGRAM_ARB, newStage.VertexProgram); Gl.glEnable(Gl.GL_VERTEX_PROGRAM_ARB);*/ // megaTextures bind a lot of images and set a lot of parameters // TODO: megatextures /*if ( newStage->megaTexture ) { newStage->megaTexture->SetMappingForSurface( tri ); idVec3 localViewer; R_GlobalPointToLocal( surf->space->modelMatrix, backEnd.viewDef->renderView.vieworg, localViewer ); newStage->megaTexture->BindForViewOrigin( localViewer ); }*/ count = newStage.VertexParameters.Length; for(int i = 0; i < count; i++) { float[] parm = new float[4]; parm[0] = registers[newStage.VertexParameters[i, 0]]; parm[1] = registers[newStage.VertexParameters[i, 1]]; parm[2] = registers[newStage.VertexParameters[i, 2]]; parm[3] = registers[newStage.VertexParameters[i, 3]]; //Gl.glProgramLocalParameter4fvARB(Gl.GL_VERTEX_PROGRAM_ARB, i, parm); } count = newStage.FragmentProgramImages.Length; for(int i = 0; i < count; i++) { if(newStage.FragmentProgramImages[i] != null) { SetTextureUnit(i); newStage.FragmentProgramImages[i].Bind(); } } //Gl.glBindProgramARB(Gl.GL_FRAGMENT_PROGRAM_ARB, newStage.FragmentProgram); //Gl.glEnable(Gl.GL_FRAGMENT_PROGRAM_ARB); // draw it DrawElementsWithCounters(tri); count = newStage.FragmentProgramImages.Length; for(int i = 1; i < count; i++) { if(newStage.FragmentProgramImages[i] != null) { SetTextureUnit(i); idE.ImageManager.BindNullTexture(); } } // TODO: megatexture /*if ( newStage->megaTexture ) { newStage->megaTexture->Unbind(); }*/ SetTextureUnit(0); //Gl.glDisable(Gl.GL_VERTEX_PROGRAM_ARB); //Gl.glDisable(Gl.GL_FRAGMENT_PROGRAM_ARB); // Fixme: Hack to get around an apparent bug in ATI drivers. Should remove as soon as it gets fixed. //Gl.glBindProgramARB(Gl.GL_VERTEX_PROGRAM_ARB, 0); //Gl.glDisableClientState(Gl.GL_COLOR_ARRAY); //Gl.glDisableVertexAttribArrayARB(9); //Gl.glDisableVertexAttribArrayARB(10); //Gl.glDisableClientState(Gl.GL_NORMAL_ARRAY); continue; } else { //-------------------------- // // old style stages // //-------------------------- // set the color float[] color = new float[4]; color[0] = registers[stage.Color.Registers[0]]; color[1] = registers[stage.Color.Registers[1]]; color[2] = registers[stage.Color.Registers[2]]; color[3] = registers[stage.Color.Registers[3]]; // skip the entire stage if an add would be black if(((stage.DrawStateBits & (MaterialStates.SourceBlendBits & MaterialStates.DestinationBlendBits)) == (MaterialStates.SourceBlendOne | MaterialStates.DestinationBlendOne)) && (color[0] <= 0) && (color[1] <= 0) && (color[2] <= 0)) { continue; } // skip the entire stage if a blend would be completely transparent if(((stage.DrawStateBits & (MaterialStates.SourceBlendBits & MaterialStates.DestinationBlendBits)) == (MaterialStates.SourceBlendSourceAlpha | MaterialStates.DestinationBlendOneMinusSourceAlpha)) && (color[3] <= 0)) { continue; } // select the vertex color source if(stage.VertexColor == StageVertexColor.Ignore) { _effect.DiffuseColor = new Vector3(color[0], color[1], color[2]); _effect.Alpha = color[3]; } else { if(stage.VertexColor == StageVertexColor.InverseModulate) { idConsole.Warning("TODO: InverseModulate"); //GL_TextureEnvironment(Gl.GL_COMBINE_ARB); /*GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.CombineRgb, (int) All.Modulate); GL.TexEnv(TextureEnvTarget.TextureEnv, TextureEnvParameter.Source0Rgb, (int) All.Texture); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_SOURCE1_RGB_ARB, Gl.GL_PRIMARY_COLOR_ARB); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_OPERAND0_RGB_ARB, Gl.GL_SRC_COLOR); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_OPERAND1_RGB_ARB, Gl.GL_ONE_MINUS_SRC_COLOR); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_RGB_SCALE_ARB, 1);*/ } // for vertex color and modulated color, we need to enable a second texture stage if(color[0] != 1 || color[1] != 1 || color[2] != 1 || color[3] != 1) { SetTextureUnit(1); idE.ImageManager.WhiteImage.Bind(); idConsole.Warning("TODO: vertex color"); // GL_TextureEnvironment(Gl.GL_COMBINE_ARB); /*Gl.glTexEnvfv(Gl.GL_TEXTURE_ENV, Gl.GL_TEXTURE_ENV_COLOR, color); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_COMBINE_RGB_ARB, Gl.GL_MODULATE); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_SOURCE0_RGB_ARB, Gl.GL_PREVIOUS_ARB); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_SOURCE1_RGB_ARB, Gl.GL_CONSTANT_ARB); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_OPERAND0_RGB_ARB, Gl.GL_SRC_COLOR); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_OPERAND1_RGB_ARB, Gl.GL_SRC_COLOR); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_RGB_SCALE_ARB, 1); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_COMBINE_ALPHA_ARB, Gl.GL_MODULATE); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_SOURCE0_ALPHA_ARB, Gl.GL_PREVIOUS_ARB); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_SOURCE1_ALPHA_ARB, Gl.GL_CONSTANT_ARB); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_OPERAND0_ALPHA_ARB, Gl.GL_SRC_ALPHA); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_OPERAND1_ALPHA_ARB, Gl.GL_SRC_ALPHA); Gl.glTexEnvi(Gl.GL_TEXTURE_ENV, Gl.GL_ALPHA_SCALE, 1); GL_SelectTexture(0);*/ } } // bind the texture BindVariableStageImage(stage.Texture, registers); // set the state SetState(stage.DrawStateBits); PrepareStageTexturing(stage, surface, tri.AmbientCache.Data); // draw it DrawElementsWithCounters(tri); FinishStageTexturing(stage, surface, tri.AmbientCache.Data); if(stage.VertexColor != StageVertexColor.Ignore) { idConsole.Warning("TODO: SVC ignore"); /*GL.DisableClientState(ArrayCap.ColorArray);*/ SetTextureUnit(1); SetTextureEnvironment(Gl.GL_MODULATE); idE.ImageManager.BindNullTexture(); SetTextureUnit(0); SetTextureEnvironment(Gl.GL_MODULATE); } } // reset polygon offset if(material.TestMaterialFlag(MaterialFlags.PolygonOffset) == true) { // TODO: Gl.glDisable(Gl.GL_POLYGON_OFFSET_FILL); } if((surface.Space.WeaponDepthHack == true) || (surface.Space.ModelDepthHack != 0.0f)) { idConsole.Warning("TODO: RB_LeaveDepthHack();"); } } }
private float _maxLights = 999; // 1.0 for standard, unlimited for floats #endregion #region Methods #region Frame control /// <summary> /// Any mirrored or portaled views have already been drawn, so prepare /// to actually render the visible surfaces for this view. /// </summary> private void BeginDrawingView() { Vector2 viewPortOffset = idE.RenderSystem.ViewPortOffset; // set the window clipping _graphicsDevice.Viewport = new Viewport( (int) viewPortOffset.X + _viewDef.ViewPort.X1, (int) viewPortOffset.Y + _viewDef.ViewPort.Y1, _viewDef.ViewPort.X2 + 1 - _viewDef.ViewPort.X1, _viewDef.ViewPort.Y2 + 1 - _viewDef.ViewPort.Y1); // the scissor may be smaller than the viewport for subviews _graphicsDevice.ScissorRectangle = new Rectangle( (int) viewPortOffset.X + _viewDef.ViewPort.X1 + _viewDef.Scissor.X1, (int) viewPortOffset.Y + _viewDef.ViewPort.Y1 + _viewDef.Scissor.Y1, _viewDef.Scissor.X2 + 1 - _viewDef.Scissor.X1, _viewDef.Scissor.Y2 + 1 - _viewDef.Scissor.Y1); _currentScissor = _viewDef.Scissor; // ensures that depth writes are enabled for the depth clear SetState(MaterialStates.DepthFunctionAlways); // we don't have to clear the depth / stencil buffer for 2D rendering if(_viewDef.ViewEntities.Count > 0) { idConsole.Warning("TODO: stencil mask"); /*Gl.glStencilMask(0xFF); // some cards may have 7 bit stencil buffers, so don't assume this // should be 128 Gl.glClearStencil(1 << (glConfig.stencilBits - 1)); Gl.glClear(Gl.GL_DEPTH_BUFFER_BIT | Gl.GL_STENCIL_BUFFER_BIT); Gl.glEnable(Gl.GL_DEPTH_TEST);*/ } else { DepthStencilState s = new DepthStencilState(); s.DepthBufferEnable = false; s.StencilEnable = false; _graphicsDevice.DepthStencilState = s; } _state.FaceCulling = CullType.None; // force face culling to set next time SetCull(CullType.Front); }
/// <summary> /// The triangle functions can check backEnd.currentSpace != surf->space /// to see if they need to perform any new matrix setup. The modelview /// matrix will already have been loaded, and backEnd.currentSpace will /// be updated after the triangle function completes. /// </summary> /// <param name="surfaces"></param> /// <param name="handler"></param> private void RenderDrawSurfaceListWithFunction(DrawSurface[] surfaces, RenderHandler handler) { int count = surfaces.Length; for(int i = 0; i < count; i++) { DrawSurface surface = surfaces[i]; // change the matrix if needed if(surface.Space != _currentSpace) { _effect.View = surface.Space.ModelViewMatrix; } if(surface.Space.WeaponDepthHack == true) { idConsole.Warning("TODO: RB_EnterWeaponDepthHack();"); } if(surface.Space.ModelDepthHack != 0.0f) { idConsole.Warning("TODO: RB_EnterModelDepthHack( drawSurf->space->modelDepthHack );"); } // change the scissor if needed if((idE.CvarSystem.GetBool("r_useScissor") == true) && (_currentScissor != surface.ScissorRectangle)) { _currentScissor = surface.ScissorRectangle; _graphicsDevice.ScissorRectangle = new Rectangle( _viewDef.ViewPort.X1 + _currentScissor.X1, _viewDef.ViewPort.Y1 + _currentScissor.Y1, _currentScissor.X2 + 1 - _currentScissor.X1, _currentScissor.Y2 + 1 - _currentScissor.Y1); } // render it handler(surface); if((surface.Space.WeaponDepthHack == true) || (surface.Space.ModelDepthHack != 0.0f)) { idConsole.Warning("TODO: RB_LeaveDepthHack();"); } _currentSpace = surface.Space; } }