1

前言

我有一个绘制以下内容的测试应用程序:

在此处输入图像描述

左三角形通过以下方式绘制:

GL.glBegin(GL.GL_TRIANGLES);
{
    for (int i = 0; i < 50; i++)
    {
        GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
        GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
        GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
        GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
        GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
        GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
    }
}
GL.glEnd();

直角三角形用以下方式绘制:

GL.glBindTexture(GL.GL_TEXTURE_2D, texture);

GL.glBegin(GL.GL_QUADS);
{
    GL.glTexCoord2f(0, 1); GL.glVertex2f(0, 1);
    GL.glTexCoord2f(0, 0); GL.glVertex2f(0, 0);
    GL.glTexCoord2f(1, 0); GL.glVertex2f(1, 0);
    GL.glTexCoord2f(1, 1); GL.glVertex2f(1, 1);
}
GL.glEnd();

纹理通过 FBO 渲染。

问题

我很难让 GL_TEXTURE_2D 和 GL_TEXTURE_3D 一起玩。一切正常,直到我取消注释以下代码部分:

GL.glEnable(GL.GL_TEXTURE_2D);
// GL.glEnable(GL.GL_TEXTURE_3D);

结果,我得到以下图像(2D 纹理停止工作):

没有任何

有没有办法让 2D 和 3D 纹理一起工作?我需要通过 FBO 将 3D 纹理渲染为 2D 纹理。有没有办法做到这一点?

完整的源代码

using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading;
using System.Drawing.Imaging;
using System.Collections.Generic;
using System.Runtime.InteropServices;

using OpenTK;
using OpenTK.Graphics;

using ManOCL;
using Monobjc.OpenGL;

using TextureTarget = OpenTK.Graphics.OpenGL.TextureTarget;

namespace Test
{
    class Program
    {       
        static void InitViewport(INativeWindow wnd, IGraphicsContext ctx)
        {
            GL.glViewport(0, 0, wnd.Width, wnd.Height);
            GL.glMatrixMode(GL.GL_PROJECTION);
            GL.glLoadIdentity();
            GL.glMatrixMode(GL.GL_MODELVIEW);
            GL.glLoadIdentity();
            
            Double aspect = 1;
            
            if (wnd.Height > 0)
            {
                aspect = wnd.Width / (double)wnd.Height;
            }

            Double square = 2;
            
            Double realWidth = square * aspect;
            
            GL.glOrtho(-realWidth * 0.5, realWidth * 0.5, -square * 0.5, square * 0.5, -1, 1);
                
            ctx.Update(wnd.WindowInfo);
        }
        
        static void InitGL(INativeWindow wnd, IGraphicsContext ctx)
        {
            GL.glShadeModel(GL.GL_SMOOTH);

            GL.glEnable(GL.GL_TEXTURE_2D);
//          GL.glEnable(GL.GL_TEXTURE_3D);
            
            GL.glEnable(GL.GL_BLEND);
            GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);

            GL.glDisable(GL.GL_DEPTH_TEST);
            
            GL.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
            GL.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        }
        
        static uint CreateTexture2D(Int32 width, Int32 height)
        {
            uint texture;
            
            GL.glGenTextures(1, out texture);
            GL.glBindTexture(GL.GL_TEXTURE_2D, texture);
            GL.glTexImage2D(GL.GL_TEXTURE_2D, 0, GL.GL_RGBA, width, height, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, IntPtr.Zero);
            GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
            GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
            GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_S, GL.GL_CLAMP);
            GL.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_WRAP_T, GL.GL_CLAMP);
            GL.glBindTexture(GL.GL_TEXTURE_2D, 0);
            
            return texture;
        }

        static uint CreateFBO()
        {
            uint fbo;
            
            GL.glGenFramebuffers(1, out fbo);
                        
            return fbo;
        }
        
        [STAThread]
        static void Main(string[] args)
        {
            Int32 strips = 32;
            Int32 stripComponents = 6;
            
            Random rand = new Random();
            
            INativeWindow wnd = new OpenTK.NativeWindow(800, 600, "OpenGL", GameWindowFlags.Default, GraphicsMode.Default, DisplayDevice.Default);
            IGraphicsContext ctx = new GraphicsContext(GraphicsMode.Default, wnd.WindowInfo);
            
            wnd.Visible = true;
            wnd.Resize += delegate { InitViewport(wnd, ctx); };
            wnd.KeyPress += delegate(object sender, OpenTK.KeyPressEventArgs e) {
                if (e.KeyChar == 'q')
                {
                    wnd.Close();
                }
                else if (e.KeyChar == '=' || e.KeyChar == '+')
                {
                    Size size = wnd.Size;
                    Point location = wnd.Location;
                    
                    wnd.Location = new Point(location.X - 16, location.Y);
                    wnd.Size = new Size(size.Width + 32, size.Height + 32);
                }
                else if (e.KeyChar == '-')
                {
                    Size size = wnd.Size;
                    Point location = wnd.Location;
                    
                    wnd.Location = new Point(location.X + 16, location.Y + 44);
                    wnd.Size = new Size(size.Width - 32, size.Height - 32);
                }
            };
            
            ctx.MakeCurrent(wnd.WindowInfo);
            ctx.LoadAll();
            
            InitGL(wnd, ctx);           
            
            Int32 width = 512;
            Int32 height = 512;
            
            uint fbo = CreateFBO();
            uint texture = CreateTexture2D(width, height);
            
            GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, fbo);
            {
                GL.glFramebufferTexture2D(GL.GL_FRAMEBUFFER, GL.GL_COLOR_ATTACHMENT0, GL.GL_TEXTURE_2D, texture, 0);
                
                GL.glPushAttrib(GL.GL_ALL_ATTRIB_BITS);
                {
                    GL.glViewport(0, 0, width, height);
                    
                    GL.glMatrixMode(GL.GL_PROJECTION);
                    GL.glLoadIdentity();
                    GL.glMatrixMode(GL.GL_MODELVIEW);
                    GL.glLoadIdentity();
                    
                    GL.glOrtho(0, 1, 0, 1, -1, 1);
                    
                    GL.glClearColor(0, 0, 0, 1.0f);
    
                    GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
                    
                    GL.glBegin(GL.GL_TRIANGLES);
                    {
                        for (int i = 0; i < 50; i++)
                        {
                            GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
                            GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
                            GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
                            GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
                            GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
                            GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
                        }
                    }
                    GL.glEnd();
                }
                GL.glPopAttrib();
            }
            GL.glBindFramebuffer(GL.GL_FRAMEBUFFER, 0);
            
            InitViewport(wnd, ctx);
            
            while (wnd.Exists)
            {
                GL.glClear(GL.GL_COLOR_BUFFER_BIT);
                
                GL.glPushMatrix();
                GL.glPushAttrib(GL.GL_TEXTURE_BIT | GL.GL_CURRENT_BIT);
                {
                    GL.glTranslatef(-0.5f, -0.5f, 0);
                    
                    GL.glPushMatrix();
                    GL.glPushAttrib(GL.GL_TEXTURE_BIT | GL.GL_CURRENT_BIT);
                    {
                        GL.glTranslatef(-0.5f, 0f, 0);
                        
                        for (int strip = 0; strip < strips; strip++)
                        {
                            GL.glBegin(GL.GL_TRIANGLE_STRIP);
                            {
                                for (int stripComponent = 0; stripComponent < stripComponents; stripComponent++)
                                {
                                    GL.glColor4d(rand.NextDouble(), rand.NextDouble(), rand.NextDouble(), rand.NextDouble());
                                    GL.glVertex2d(rand.NextDouble(), rand.NextDouble());
                                }
                            }
                            GL.glEnd();
                        }
                    }
                    GL.glPopAttrib();
                    GL.glPopMatrix();

                    GL.glPushMatrix();
                    GL.glPushAttrib(GL.GL_TEXTURE_BIT | GL.GL_CURRENT_BIT);
                    {
                        GL.glTranslatef(0.5f, 0f, 0);
                        
                        GL.glColor4f(1, 1, 1, 1);
                        
                        GL.glBindTexture(GL.GL_TEXTURE_2D, texture);
                        
                        GL.glBegin(GL.GL_QUADS);
                        {
                            GL.glTexCoord2f(0, 1); GL.glVertex2f(0, 1);
                            GL.glTexCoord2f(0, 0); GL.glVertex2f(0, 0);
                            GL.glTexCoord2f(1, 0); GL.glVertex2f(1, 0);
                            GL.glTexCoord2f(1, 1); GL.glVertex2f(1, 1);
                        }
                        GL.glEnd();
                    }
                    GL.glPopAttrib();
                    GL.glPopMatrix();
                }
                GL.glPopAttrib();               
                GL.glPopMatrix();
                
                ctx.SwapBuffers();
                wnd.ProcessEvents();
            }
        }
    }
}
4

1 回答 1

7

OpenGL 具有纹理目标的优先级:GL_TEXTURE_3D 覆盖 GL_TEXTURE_2D,后者覆盖 GL_TEXTURE_1D。由于一次只能在一个纹理单元中激活一个目标,因此具有最高优先级的纹理目标将提供采样数据。

要同时使用多个纹理(独立于它们的目标),您必须使用多重纹理。查看多纹理教程以了解如何使用它们。在固定管道与可编程(=着色器)管道中使用多纹理的方式之间存在一些细微差别。http://www.clockworkcoders.com/oglsl/tutorial8.htm

于 2011-08-03T10:11:41.337 回答