OpenGL尝试绘制多个2D纹理,但只有第一个出现。

3

我有一个问题,正在尝试使用纹理(每个星球都有一张纹理)绘制太阳系,但在绘制纹理时只有第一个出现了,其他的都没有。

我的初始化函数遍历我的文件,将纹理保存到一个对象中,并遍历该对象。在迭代过程中,它生成并使用OpenGL调用将纹理绑定到名称上。

        SharpGL.OpenGL gl = args.OpenGL;
        gl.Enable(SharpGL.OpenGL.GL_BLEND);
        gl.Enable(SharpGL.OpenGL.GL_TEXTURE_2D);
        gl.BlendFunc(SharpGL.Enumerations.BlendingSourceFactor.SourceAlpha, SharpGL.Enumerations.BlendingDestinationFactor.OneMinusSourceAlpha);                        
        gl.ClearColor(0, 0, 0, 1);

        foreach (ImageWrapper iw in m_images)
        {                            
            uint[] texNames = new uint[1];

            gl.GenTextures(1, texNames);
            gl.BindTexture(SharpGL.OpenGL.GL_TEXTURE_2D, texNames[0]);

            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_WRAP_S, SharpGL.OpenGL.GL_REPEAT);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_WRAP_T, SharpGL.OpenGL.GL_REPEAT);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_MAG_FILTER, SharpGL.OpenGL.GL_LINEAR);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_MIN_FILTER, SharpGL.OpenGL.GL_LINEAR);

            gl.TexImage2D(SharpGL.OpenGL.GL_TEXTURE_2D,
                          0,
                          3,
                          iw.BitmapSource.PixelWidth,
                          iw.BitmapSource.PixelHeight,
                          0,
                          SharpGL.OpenGL.GL_BGRA,
                          SharpGL.OpenGL.GL_UNSIGNED_BYTE,
                          iw.Pixels);

            iw.TextureHandle = texNames;

        }

这是我的绘制所有内容的函数。我遍历了所有具有纹理数据的对象,并尝试逐个绘制它们。为了让我的太阳系旋转,我还想执行一些旋转和变换。对于出现的纹理部分,这部分工作正常。
        SharpGL.OpenGL gl = args.OpenGL;
        gl.Clear(SharpGL.OpenGL.GL_COLOR_BUFFER_BIT | SharpGL.OpenGL.GL_DEPTH_BUFFER_BIT );
        gl.LoadIdentity();

        float[] data = new float[4];
        foreach (ImageWrapper iw in m_images)
        {
            //gl.MatrixMode(SharpGL.Enumerations.MatrixMode.Modelview);                

            gl.Ortho2D(0, this.Width, 0, this.Height);                
            gl.Enable(OpenGL.GL_TEXTURE_2D);                
            gl.BindTexture(OpenGL.GL_TEXTURE_2D, iw.TextureHandle[0]);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_WRAP_S, SharpGL.OpenGL.GL_REPEAT);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_WRAP_T, SharpGL.OpenGL.GL_REPEAT);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_MAG_FILTER, SharpGL.OpenGL.GL_LINEAR);
            gl.TexParameter(SharpGL.OpenGL.GL_TEXTURE_2D, SharpGL.OpenGL.GL_TEXTURE_MIN_FILTER, SharpGL.OpenGL.GL_LINEAR);


            gl.PushMatrix();
            //gl.Translate(this.Width / 2, this.Height / 2, 0);               

            //gl.Rotate(iw.RotationAboutSun, 0, 0, 1);
            //gl.Translate(iw.X + 1 * this.Width / 2, iw.Y + 1 * this.Height / 2, 0);
            gl.Translate(32,32, 0);
            //gl.Rotate(iw.RotationAboutAxis, 0, 0, 1);  
            //

            gl.Begin(SharpGL.Enumerations.BeginMode.Quads);
            gl.Color(new float[] { 1f,1f,1f});                                          
            gl.TexCoord(0,0);
            gl.Vertex(new double[] { 0 - iw.PixelWidth / 2, 0 - iw.PixelHeight / 2});                
            gl.TexCoord(0,1);
            gl.Vertex(new double[] { 32 - iw.PixelWidth / 2, 0 - iw.PixelHeight / 2 });               
            gl.TexCoord(1,1);
            gl.Vertex(new double[] { 32 - iw.PixelWidth / 2, 32 - iw.PixelHeight / 2 });
            gl.TexCoord(1,0);
            gl.Vertex(new double[] { 0 - iw.PixelWidth / 2, 32 - iw.PixelHeight / 2 });                            
            gl.End();

            gl.PopMatrix();

            gl.Disable(OpenGL.GL_TEXTURE_2D);                

        }

我正在使用C#中的SharpGL库来完成这个任务。


我没有看到任何不寻常的事情。你确定m_images中所有元素的Pixels成员都被正确填充了吗? - Nathan Monteleone
是的,我刚刚检查了一下。看起来没问题。 - mj_
看起来你忘记了 glActiveTexture 函数的调用。在绑定纹理之前需要先调用它们。 - danijar
2个回答

2

gluOrtho2D()没有像你期望的那样发出glLoadIdentity()命令。

通常情况下,每帧只需设置一次投影矩阵。

尝试使用以下代码:

void DrawFrame()
{
    ...

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluOrtho2D(0, this.Width, 0, this.Height);

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    // "camera" transform(s)

    foreach object
    {
        glPushMatrix();
        // per-object matrix transform(s)

        // draw object

        glPopMatrix();
    }
}

万岁!做到了! - mj_
@mj_: 很高兴问题很容易解决 :) - genpfault
1
@genpfault:只是挑刺一下,你每次渲染通道都设置了投影矩阵,即为3D场景设置一次,为HUD设置一次,等等。 - datenwolf
@datenwolf 为什么在一个帧中多次设置投影矩阵是不好的做法?如果您想先绘制一些2D内容,然后是3D内容,最后是其他应该显示在所有其他内容之上的2D内容,那么这不是必要的吗? - Maghoumi
1
@M2X:我从未说过多次设置它是不好的做法。相反,我是OpenGL状态设置的支持者之一,只要有必要就进行设置,以确保您不会因为没有固定状态而出现问题。对于现代OpenGL,您必须为每个着色器程序设置uniforms。 - datenwolf

0

刚刚遇到了这个问题,所以我也想加入讨论。
我看到了被接受的答案,在我的情况下,我确实正确地重置了管道中的所有内容。在我的管道中,我需要渲染3D和2D对象。对于3D对象,我会切换到3D投影/模型视图,对于2D对象,我会切换到正交投影。

然而,当我想要渲染几个文本块(使用四边形和纹理)时,只有第一个纹理被渲染。深度测试是我的问题根源。因此,我修改了上面的代码以适应我的情况。

void DrawFrame()
{
    foreach object
    {
        drawObject();   // Is an abstract method
    }
}


void _3DObject::drawObject() {
    switchTo3D();

    // Camera transform

    glPushMatrix();
    .
    . // Draw
    .
    .glPopMatrix();
}

void _2DObject::drawObject() {
    switchTo2D();

    // Having depth testing enabled was causing
    // problems when rendering textured quads.
    glDisable(GL_DEPTH_TEST);

    // Camera transform

    glPushMatrix();
    .
    . // Draw
    .
    .glPopMatrix();

    glEnable(GL_DEPTH_TEST);
}

PS:这里的“刚刚”指的是一个月前!不知道为什么我忘记早点发布这个答案了 :(


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接