Как я отрисовываю сцену в текстуру куба, а затем использую текстуру куба в другом шейдере в качестве кубического семплера? - PullRequest
2 голосов
/ 23 июня 2019

Я пишу 3D-движок, который использует шейдеры Phong и точечные источники света в C #, используя библиотеку OpenTK (OpenGL).Сейчас я пытаюсь создать карту теней (кубическую карту) сцены для каждого имеющегося у меня источника света, но я не знаю, как увидеть, работает ли рендеринг кубической карты, и я не знаю, как затем передать кубическую карту как равномерную.CubeSampler для шейдера.

Я пытался (для каждого источника света) создать новую текстуру кубической карты с помощью GenTexture, затем связать текстуру и использовать TexImage2D на каждой грани кубической карты.Затем создайте кадровый буфер с текстурой куба и буфером глубины.Затем визуализируем сцену, используя указанный кадровый буфер, чтобы раскрасить Attachment0.

. Для использования в шейдере я просто получаю единое местоположение и привязываю id текстуры кубической карты.

Где я создаю кубическую карту

 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);

        }

Рендеринг каждой сетки (где я хочу передать кубическую карту)

// 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();
        }

После всего этого CubeSamplers вшейдер кажется пустым (все значения 0).

Я впервые публикую здесь что-то.Извините, если я сделал что-то не так.

...