C# 如何将场景渲染为立方体纹理,然后将另一个着色器中的立方体纹理用作立方体样例?
我正在使用OpenTK库(OpenGL)编写一个使用Phong着色器和C#中的点光源的3D引擎。我现在正尝试为我拥有的每个灯光创建场景的阴影贴图(立方体贴图),但我不知道如何查看立方体贴图的渲染是否有效,我也不知道如何将立方体贴图作为统一立方体样例传递给着色器 我尝试(针对每个灯光)使用GenTexture创建一个新的立方体贴图纹理,然后绑定纹理并在立方体贴图的每个面上使用TexImage2D。然后使用立方体纹理和深度缓冲区创建帧缓冲区。然后使用所述帧缓冲区将场景渲染为颜色附件0 为了在着色器中使用它,我只需要获得统一的位置并绑定立方体贴图纹理的id 在这里我创建了立方体贴图C# 如何将场景渲染为立方体纹理,然后将另一个着色器中的立方体纹理用作立方体样例?,c#,opengl,shadow,opentk,C#,Opengl,Shadow,Opentk,我正在使用OpenTK库(OpenGL)编写一个使用Phong着色器和C#中的点光源的3D引擎。我现在正尝试为我拥有的每个灯光创建场景的阴影贴图(立方体贴图),但我不知道如何查看立方体贴图的渲染是否有效,我也不知道如何将立方体贴图作为统一立方体样例传递给着色器 我尝试(针对每个灯光)使用GenTexture创建一个新的立方体贴图纹理,然后绑定纹理并在立方体贴图的每个面上使用TexImage2D。然后使用立方体纹理和深度缓冲区创建帧缓冲区。然后使用所述帧缓冲区将场景渲染为颜色附件0 为了在着色器中
public Light Init(Scene scene)
{
texId = GL.GenTexture();
GL.BindTexture(TextureTarget.TextureCubeMap, texId);
for (int i = 0; i < 6; i++)
{
GL.TexImage2D(TextureTarget.TextureCubeMapPositiveX + i, 0, PixelInternalFormat.Rgba8, 512, 512, 0, PixelFormat.Rgba, PixelType.UnsignedByte, (IntPtr)null);
}
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (float)TextureMagFilter.Linear);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (float)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (float)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (float)TextureWrapMode.ClampToEdge);
GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (float)TextureWrapMode.ClampToEdge);
GL.BindTexture(TextureTarget.TextureCubeMap, 0);
fbo = GL.GenFramebuffer();
GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo);
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
fbo_depth = GL.GenRenderbuffer();
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, fbo_depth);
GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent24, 512, 512);
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, fbo_depth);
GL.Viewport(0, 0, 512, 512);
for (int i = 0; i < 6; i++)
{
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,
FramebufferAttachment.ColorAttachment0,
TextureTarget.TextureCubeMapPositiveX + i, texId, 0);
cam.SwitchFace(i);
scene.RenderLowRes(cam);
}
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
GL.Viewport(0, 0, 1024, 1024);
return this;
}
public void RenderLowRes(CubeCamera cam)
{
GL.ClearColor(1, 1, 1, 1);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.Clear(ClearBufferMask.DepthBufferBit);
sceneTree.RenderShade(shady, cam.view, cam.projection);
}
渲染每个网格(我要通过立方体贴图的位置)
完成所有这些操作后,着色器中的立方体示例将显示为空(所有值均为0)
这是我第一次在这里发帖。如果我做错了什么,很抱歉。您必须渲染场景6次,我需要为立方体贴图的每一侧渲染一次。您可以将立方体贴图的一侧附着到frambuffer。e、 g.
glFramebufferTexture2D(GL\u帧缓冲区、GL\u颜色、GL\u附件0、GL\u纹理、立方体、贴图、正片、立方体、0)
// render the mesh using the supplied shader and matrix
public void Render( Shader shader, Matrix4 transform, Texture texture)
{
// on first run, prepare buffers
Prepare( shader );
// safety dance
GL.PushClientAttrib( ClientAttribMask.ClientVertexArrayBit );
// enable texture
int texLoc = GL.GetUniformLocation( shader.programID, "pixels" );
GL.Uniform1( texLoc, 0 );
GL.ActiveTexture( TextureUnit.Texture0 );
GL.BindTexture( TextureTarget.Texture2D, texture.id );
// enable shader
GL.UseProgram( shader.programID );
// pass the cubesamplers.For now only pass one of them to test
int map3Loc = GL.GetUniformLocation(shader.programID, "lamp3Map");
GL.Uniform1(map3Loc, 0);
GL.ActiveTexture(TextureUnit.Texture1);
GL.BindTexture(TextureTarget.TextureCubeMap, Scene.lights[3].texId);
// pass lamps to vertex shader
Matrix2x3 lamp1data = new Matrix2x3(Scene.lights[0].node.myTrans.Row3.Xyz, Scene.lights[0].color);
GL.UniformMatrix2x3(shader.uniform_lamp1, false, ref lamp1data);
Matrix2x3 lamp2data = new Matrix2x3(Scene.lights[1].node.myTrans.Row3.Xyz, Scene.lights[1].color);
GL.UniformMatrix2x3(shader.uniform_lamp2, false, ref lamp2data);
Matrix2x3 lamp3data = new Matrix2x3(Scene.lights[2].node.myTrans.Row3.Xyz, Scene.lights[2].color);
GL.UniformMatrix2x3(shader.uniform_lamp3, false, ref lamp3data);
Matrix2x3 lamp4data = new Matrix2x3(Scene.lights[3].node.myTrans.Row3.Xyz, Scene.lights[3].color);
GL.UniformMatrix2x3(shader.uniform_lamp4, false, ref lamp4data);
// Console.WriteLine(lamp1data.Row0.ToString());
//Matrix2x3 lamp1 = new Matrix2x3(lamp, new Vector3(1, 1, 1)); //pos, color
// pass transform to vertex shader
GL.UniformMatrix4( shader.uniform_mview, false, ref transform );
// enable position, normal and uv attributes
GL.EnableVertexAttribArray( shader.attribute_vpos );
GL.EnableVertexAttribArray( shader.attribute_vnrm );
GL.EnableVertexAttribArray( shader.attribute_vuvs );
// bind interleaved vertex data
GL.EnableClientState( ArrayCap.VertexArray );
GL.BindBuffer( BufferTarget.ArrayBuffer, vertexBufferId );
GL.InterleavedArrays( InterleavedArrayFormat.T2fN3fV3f, Marshal.SizeOf( typeof( ObjVertex ) ), IntPtr.Zero );
// link vertex attributes to shader parameters
GL.VertexAttribPointer( shader.attribute_vuvs, 2, VertexAttribPointerType.Float, false, 32, 0 );
GL.VertexAttribPointer( shader.attribute_vnrm, 3, VertexAttribPointerType.Float, true, 32, 2 * 4 );
GL.VertexAttribPointer( shader.attribute_vpos, 3, VertexAttribPointerType.Float, false, 32, 5 * 4 );
// bind triangle index data and render
GL.BindBuffer( BufferTarget.ElementArrayBuffer, triangleBufferId );
GL.DrawArrays( PrimitiveType.Triangles, 0, triangles.Length * 3 );
// bind quad index data and render
if( quads.Length > 0 )
{
GL.BindBuffer( BufferTarget.ElementArrayBuffer, quadBufferId );
GL.DrawArrays( PrimitiveType.Quads, 0, quads.Length * 4 );
}
// restore previous OpenGL state
GL.UseProgram( 0 );
GL.PopClientAttrib();
}