Opengl 在透明图形上使用深度测试

Opengl 在透明图形上使用深度测试,opengl,alpha,blend,depth-buffer,Opengl,Alpha,Blend,Depth Buffer,我尝试使用深度测试和alpha混合。我想做的是把一个不透明的小环放在一个更大的透明环里面。我应该启用深度测试,以防止不良的几何图形。所以如果我启用深度测试,我就不能显示内环。是否有解决此问题的方法。谢谢你的帮助。我的代码如下所示: #include <GLTools.h> // OpenGL toolkit #include <GLMatrixStack.h> #include <GLFrame.h> #include <GLFrustum.h&g

我尝试使用深度测试和alpha混合。我想做的是把一个不透明的小环放在一个更大的透明环里面。我应该启用深度测试,以防止不良的几何图形。所以如果我启用深度测试,我就不能显示内环。是否有解决此问题的方法。谢谢你的帮助。我的代码如下所示:

   #include <GLTools.h> // OpenGL toolkit
#include <GLMatrixStack.h>
#include <GLFrame.h>
#include <GLFrustum.h>
#include <GLGeometryTransform.h>
#include <GLShaderManager.h>
#include <math3d.h>

#include <math.h>
#define FREEGLUT_STATIC
#include <GL\glut.h>

GLFrame viewFrame;
GLFrustum viewFrustum;
GLBatch triangleBatch;
GLTriangleBatch torusBatch;
GLTriangleBatch torusBatch2;
GLMatrixStack modelViewMatrix;
GLMatrixStack projectionMatrix;
GLGeometryTransform transformPipeline;
GLShaderManager shaderManager;

// Flags for effects
bool iCull = true;
bool iDepth = true;

GLfloat blockSize = 0.3f;
GLfloat vVerts[] ={-blockSize, -blockSize, 0.0f,
                    blockSize, -blockSize, 0.0f,
                    blockSize, blockSize, 0.0f};

void ProcessMenu(int value)
{
    switch(value)
    {
        case 1:
            iDepth = !iDepth;
            break;

        case 2:
            iCull = !iCull;
            break;

        case 3:
            glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
            break;

        case 4:
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            break;

        case 5:
            glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
            break;
        case 6:
            glPolygonMode(GL_FRONT, GL_LINE);
            break;
    }

    glutPostRedisplay();
}

void bounceFunction(void)
{
    static GLfloat xDir = 1.0f;
    static GLfloat yDir = 1.0f;

    GLfloat stepSize = 0.0005f;

    GLfloat blockX = vVerts[0];   // Upper left X
    GLfloat blockY = vVerts[7];  // Upper left Y

    blockY += stepSize * yDir;
    blockX += stepSize * xDir;

    if(blockX < -1.0f) {                  blockX = -1.0f; xDir *= -1.0f; }
    if(blockX > (1.0f - blockSize * 2)) { blockX = 1.0f - blockSize * 2; xDir *= -1.0f; }
    if(blockY < -1.0f + blockSize * 2)  { blockY = -1.0f + blockSize * 2; yDir *= -1.0f; }
    if(blockY > 1.0f) {                   blockY = 1.0f; yDir *= -1.0f; }

    vVerts[0] = blockX;
    vVerts[1] = blockY - blockSize*2;

    vVerts[3] = blockX + blockSize*2;
    vVerts[4] = blockY - blockSize*2;

    vVerts[6] = blockX + blockSize*2;
    vVerts[7] = blockY;


}

void movementKeys(int key, int x, int y)
{
    /*GLfloat stepSize = 0.025f;
    GLfloat blockX = vVerts[0];
    GLfloat blockY = vVerts[7];

    if(key == GLUT_KEY_UP)
        blockY += stepSize;
    if(key == GLUT_KEY_DOWN)
        blockY -= stepSize;
    if(key == GLUT_KEY_LEFT)
        blockX -= stepSize;
    if(key == GLUT_KEY_RIGHT)
        blockX += stepSize;

    //CollisonDetection

    if(blockX < -1.0f)                  blockX = -1.0f;
    if(blockX > (1.0f - blockSize * 2)) blockX = 1.0f - blockSize * 2;;
    if(blockY < -1.0f + blockSize * 2)  blockY = -1.0f + blockSize * 2;
    if(blockY > 1.0f)                   blockY = 1.0f;

    //CollisonDetection end

    //Recalculation
    vVerts[0] = blockX;
    vVerts[1] = blockY - blockSize*2;

    vVerts[3] = blockX + blockSize*2;
    vVerts[4] = blockY - blockSize*2;

    vVerts[6] = blockX + blockSize*2;
    vVerts[7] = blockY;

    triangleBatch.CopyVertexData3f(vVerts);
    glutPostRedisplay();*/
    if(key == GLUT_KEY_UP)
        viewFrame.RotateWorld(m3dDegToRad(-5.0), 1.0f, 0.0f, 0.0f);

    if(key == GLUT_KEY_DOWN)
        viewFrame.RotateWorld(m3dDegToRad(5.0), 1.0f, 0.0f, 0.0f);

    if(key == GLUT_KEY_LEFT)
        viewFrame.RotateWorld(m3dDegToRad(-5.0), 0.0f, 1.0f, 0.0f);

    if(key == GLUT_KEY_RIGHT)
        viewFrame.RotateWorld(m3dDegToRad(5.0), 0.0f, 1.0f, 0.0f);

    // Refresh the Window
    glutPostRedisplay();

}

void changeSize(int w, int h)
{
    // Prevent a divide by zero
    if(h == 0)
        h = 1;

    // Set Viewport to window dimensions
    glViewport(0, 0, w, h);

    viewFrustum.SetPerspective(35.0f, float(w)/float(h), 1.0f, 100.0f);

    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
}

void renderScene()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    // Turn culling on if flag is set
    if(iCull)
        glEnable(GL_CULL_FACE);
    else
        glDisable(GL_CULL_FACE);

    // Enable depth testing if flag is set
    if(iDepth)
        glEnable(GL_DEPTH_TEST);
    else
        glDisable(GL_DEPTH_TEST);

    modelViewMatrix.PushMatrix(viewFrame);
    glPolygonOffset(-1.0f, -1.0f);

    GLfloat vRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
    GLfloat vBlue[] = {0.0f, 0.0f, 1.0f, 0.5f};

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vRed);
    torusBatch.Draw();



    shaderManager.UseStockShader(GLT_SHADER_DEFAULT_LIGHT, transformPipeline.GetModelViewMatrix(), transformPipeline.GetProjectionMatrix(), vBlue);
    torusBatch2.Draw();
    glDisable(GL_BLEND);

    modelViewMatrix.PopMatrix();

    glutSwapBuffers();
}

void SetupRC()
{
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);//Backgroung color

    shaderManager.InitializeStockShaders();
    viewFrame.MoveForward(7.0f);
    gltMakeTorus(torusBatch, 1.0f, 0.25f, 52, 26);
    gltMakeTorus(torusBatch2, 0.95f, 0.1f, 52, 26);

    triangleBatch.Begin(GL_TRIANGLES, 3);
    triangleBatch.CopyVertexData3f(vVerts);
    triangleBatch.End();
}


int main(int argc, char* argv[])
{
    gltSetWorkingDirectory(argv[0]);

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
    glutInitWindowSize(1280,720);
    glutCreateWindow("Test");


    GLenum err = glewInit();

    if(err != GLEW_OK)
    {
        //Error handling
        fprintf(stderr, "GLEW error: %s\n", glewGetErrorString(err));
        return -1;
    }

    glutReshapeFunc(changeSize);
    glutDisplayFunc(renderScene);
    glutSpecialFunc(movementKeys);

    // Create the Menu
    glutCreateMenu(ProcessMenu);
    glutAddMenuEntry("Toggle depth test",1);
    glutAddMenuEntry("Toggle cull backface",2);
    glutAddMenuEntry("Set Fill Mode", 3);
    glutAddMenuEntry("Set Line Mode", 4);
    glutAddMenuEntry("Set Point Mode", 5);
    glutAddMenuEntry("Set Line Mode Back Face Culling", 6);

    glutAttachMenu(GLUT_RIGHT_BUTTON);

    SetupRC();

    glutMainLoop();
    return 0;
}
#包括//OpenGL工具包
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义FREEGLUT\u静态
#包括
GLFrame视框;
GLFrustum viewFrustum;
GLBatch三角板;
GLTriangleBatch-torusBatch;
GLTriangleBatch torusBatch2;
GLMatrixStack模型视图矩阵;
GLMatrixStack投影矩阵;
GLGEOMETRY变换管道;
GLShaderManager shaderManager;
//效果标志
bool icul=真;
bool iDepth=真;
GLfloat blockSize=0.3f;
GLfloat vVerts[]={-blockSize,-blockSize,0.0f,
块大小,-块大小,0.0f,
块大小,块大小,0.0f};
无效进程菜单(int值)
{
开关(值)
{
案例1:
iDepth=!iDepth;
打破
案例2:
icul=!icul;
打破
案例3:
glPolygonMode(GLU前、后、GLU填充);
打破
案例4:
glPolygonMode(GLU前、后、GLU线);
打破
案例5:
glPolygonMode(GLU前、后、GLU点);
打破
案例6:
glPolygonMode(GL_前端,GL_线);
打破
}
再发现();
}
void反弹函数(void)
{
静态GLfloat xDir=1.0f;
静态GLYDIR=1.0f;
GLfloat步长=0.0005f;
GLfloat blockX=vVerts[0];//左上角X
GLfloat blockY=vVerts[7];//左上角Y
blockY+=步长*yDir;
blockX+=步长*xDir;
如果(blockX<-1.0f){blockX=-1.0f;xDir*=-1.0f;}
如果(blockX>(1.0f-blockSize*2)){blockX=1.0f-blockSize*2;xDir*=-1.0f;}
如果(blockY<-1.0f+blockSize*2){blockY=-1.0f+blockSize*2;yDir*=-1.0f;}
如果(blockY>1.0f){blockY=1.0f;yDir*=-1.0f;}
vVerts[0]=块X;
vVerts[1]=块-块大小*2;
vVerts[3]=块X+块大小*2;
vVerts[4]=块-块大小*2;
vVerts[6]=块X+块大小*2;
vVerts[7]=块状;
}
无效移动键(整数键、整数x、整数y)
{
/*GLfloat步长=0.025f;
GLfloat blockX=vVerts[0];
GLfloat blockY=vVerts[7];
if(key==GLUT\u key\u UP)
块状+=步长;
如果(键==GLUT\U键\U向下)
块状-=步长;
if(key==GLUT\u key\u LEFT)
blockX-=步长;
if(key==GLUT\u key\u RIGHT)
blockX+=步长;
//碰撞检测
如果(blockX<-1.0f)blockX=-1.0f;
如果(blockX>(1.0f-块大小*2))blockX=1.0f-块大小*2;;
如果(blockY<-1.0f+blockSize*2)blockY=-1.0f+blockSize*2;
如果(blockY>1.0f),blockY=1.0f;
//碰撞检测端
//重新计算
vVerts[0]=块X;
vVerts[1]=块-块大小*2;
vVerts[3]=块X+块大小*2;
vVerts[4]=块-块大小*2;
vVerts[6]=块X+块大小*2;
vVerts[7]=块状;
triangleBatch.CopyVertexData3f(vVerts);
再发现()*/
if(key==GLUT\u key\u UP)
视框旋转旋转旋转(m3dDegToRad(-5.0)、1.0f、0.0f、0.0f);
如果(键==GLUT\U键\U向下)
视框旋转旋转旋转(m3dDegToRad(5.0)、1.0f、0.0f、0.0f);
if(key==GLUT\u key\u LEFT)
视框旋转旋转旋转(m3dDegToRad(-5.0)、0.0f、1.0f、0.0f);
if(key==GLUT\u key\u RIGHT)
视框旋转旋转旋转(m3dDegToRad(5.0)、0.0f、1.0f、0.0f);
//刷新窗口
再发现();
}
无效更改大小(整数w、整数h)
{
//防止被零除
如果(h==0)
h=1;
//将视口设置为窗口尺寸
glViewport(0,0,w,h);
视锥台设置透视图(35.0f,浮动(w)/浮动(h),1.0f,100.0f);
LoadMatrix(viewFrustum.GetProjectionMatrix());
transformPipeline.SetMatrixStacks(modelViewMatrix、projectionMatrix);
}
void renderScene()
{
glClear(GL|U颜色|U缓冲|位| GL|U深度|U缓冲|位| GL|U模具|U缓冲|位);
//如果设置了标记,则启用消隐
if(Iull)
glEnable(GL_CULL_面);
其他的
glDisable(GLU消隐面);
//如果设置了标记,则启用深度测试
if(iDepth)
glEnable(GLU深度试验);
其他的
glDisable(GLU深度测试);
modelViewMatrix.PushMatrix(viewFrame);
glPolygonOffset(-1.0f,-1.0f);
GLfloat vRed[]={1.0f,0.0f,0.0f,0.5f};
GLfloat vBlue[]={0.0f,0.0f,1.0f,0.5f};
glEnable(GL_混合物);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_减去GL_SRC_ALPHA);
UseStockShader(GLT_SHADER_DEFAULT_LIGHT,transformPipeline.GetModelViewMatrix(),transformPipeline.GetProjectionMatrix(),vRed);
torusBatch.Draw();
UseStockShader(GLT_SHADER_DEFAULT_LIGHT、transformPipeline.GetModelViewMatrix()、transformPipeline.GetProjectionMatrix()、vBlue);
torusBatch2.Draw();
glDisable(GLU混合);
modelViewMatrix.PopMatrix();
glutSwapBuffers();
}
void SetupRC()
{
glClearColor(0.5f,0.5f,0.5f,1.0f);//背景颜色
shaderManager.InitializeStockShaders();
视图框。向前移动(7.0f);
gltMakeTorus(torusBatch,1.0f,0.25f,52,26);
gltMakeTorus(torusBatch2,0.95f,0.1f,52,26);
三角面片。开始(三角面片,3);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.End();
}
int main(int argc,char*argv[])
{
gltSetWorkingDirectory(argv[0]);
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_双精度| GLUT_RGBA | GLUT_深度| GLUT_模具);
GLUTinitWindowsSize(1280720);
测试窗口(“测试”);
GLenum err=glewInit();
如果(错误!=GLEW_OK)
{
//错误处理
fprintf(stderr,“GLEW错误:%s\n”,glewGetErrorString(err));
雷图