2

我正在openGL中制作一个粒子喷泉,我的粒子功能正常。我决定添加一架飞机,让它看起来像是从飞机上弹起。我想要得到的是这样的 在此处输入图像描述

不幸的是,我得到的是这个

在此处输入图像描述

平原似乎根本没有出现。我尝试弄乱坐标,但这似乎没有任何作用。是我用作纹理的图像,它是 256 X 256 24 位 bmp。

我在 init 函数中加载纹理,然后在渲染粒子之前在以下函数中调用它

void Load_Plane(){
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
    glColor4f(0.0f, 0.2f, 0.2f, 0.5f);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, txPlane);
    glBegin(GL_QUADS);
        glNormal3f(-10.0f, 0.0f, -10.0f);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(-10.0f, 0.0f, 10.0f);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f( 10.0f, 0.0f, 10.0f);
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f( 10.0f, 0.0f, -10.0f);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(-10.0f, 0.0f, -10.0f);
    glEnd();
}

完整代码

// particle_fountain.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include<stdlib.h>
#include <stdio.h>
#include<Windows.h>
#include <time.h>
#include <GL\glut.h>
#include<GL\GLU.h>

#define MAX_PARTICLES 200 //max number of particles
#define MAX_BOUNCE_COUNT 5 //number of times a particle should bounce 
#define MAX_PARTICLE_AGE 95

//Colours
float R = 0.8f;
float G = 0.2f;
float B = 0.0f;
float cR = 0.001f;
float cG = 0.002f;
float cB = 0.003f;
float Size = 0.02f; //size for points
GLuint txParticle;
GLuint txPlane;


struct PARTICLE {
    float X,Y,Z; // Current position
    float sX,sY,sZ; // Current Speed/Movement
    float tX,tY,tZ; // Target Speed/Movement
    float R,B,G; // Particle Colour
    bool Active; // Is particle Active
    int Age; // Age of the particle
    int MaxAge; // Maximum Age before particle dies
    int BounceCount;
} Particles[MAX_PARTICLES];

void Init_Particles();
void Activate_Particles();
void Adjust_Particles();
void Render_Particles();
bool LoadBitmapTexture(char * FileName, GLuint &texid);
void timer(int extra);
void Load_Plane();
void DrawGLscene();
void Reshape(GLsizei w, GLsizei h);

int main(int argc, char** argv){
     glutInit(&argc,argv);
    glutInitDisplayMode( GLUT_RGBA| GLUT_DOUBLE );
    glutInitWindowSize( 640, 480 );    
    glutCreateWindow("Particle fountain");

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1.0, 1.0, -1.0, 1.0, 1.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0, -0.9, -3.0); 


    Init_Particles();
    glutDisplayFunc(DrawGLscene);
    glutTimerFunc(0, timer, 0);
    glutMainLoop();

}

void timer(int extra)
{
    glutPostRedisplay();
    glutTimerFunc(20, timer, 0);
}

void Load_Plane(){
    glEnable(GL_BLEND);
    glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
    glColor4f(0.0f, 0.2f, 0.2f, 0.5f);
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, txPlane);
    glBegin(GL_QUADS);
        glNormal3f(-10.0f, 0.0f, -10.0f);
        glTexCoord2f(0.0f, 0.0f);
        glVertex3f(-10.0f, 0.0f, 10.0f);
        glTexCoord2f(1.0f, 0.0f);
        glVertex3f( 10.0f, 0.0f, 10.0f);
        glTexCoord2f(1.0f, 1.0f);
        glVertex3f( 10.0f, 0.0f, -10.0f);
        glTexCoord2f(0.0f, 1.0f);
        glVertex3f(-10.0f, 0.0f, -10.0f);
    glEnd();
}
void DrawGLscene(){
    Load_Plane();
    glPushMatrix();
    glScalef(1.0f, -1.0f, 1.0f);
    Render_Particles();
    glPopMatrix();
    Render_Particles();

}


void Init_Particles(){
    LoadBitmapTexture("./Particle.bmp", txParticle); //load the particle texture 
    LoadBitmapTexture("./Plain.bmp",txPlane); //load the plain texture

    int p;
    srand((int)time(NULL));
    for(p=0; p<MAX_PARTICLES; p++){
        Particles[p].Active = FALSE;
        Particles[p].tX = 0.0f;
        Particles[p].tY = -0.1f;
        Particles[p].tZ = 0.0f;
    }
}

void Activate_Particles(){
    int p;
    for(p=0; p<MAX_PARTICLES; p++){
        if(!Particles[p].Active){
            // Start the particle at 0,0,0 origin
            Particles[p].X = 0.0f;
            Particles[p].Y = 0.0f;
            Particles[p].Z = 0.0f;
            // The following lines set a random speed value
            Particles[p].sX = (((float)((rand() % 100) + 1)) /
                1000.0f) - 0.05f;
            Particles[p].sY = (((float)((rand() % 100) + 50)) /
                500.0f);
            Particles[p].sZ = (((float)((rand() % 100) + 1)) /
                1000.0f) - 0.05f;
            // We also activate the particle
            Particles[p].Active = true;
            // Set it's Age to zero
            Particles[p].Age = 0;
            // We also assign a max age to the particles
            Particles[p].MaxAge = MAX_PARTICLE_AGE;
            // We Also reset the bouncecount to zero
            Particles[p].BounceCount = 0;

            //Adding the colours
            Particles[p].R = R;
            Particles[p].G = G;
            Particles[p].B = B;
            R+=cR;
            G+=cG;
            B+=cB;
            if(R>1.0f){R=1.0f; cR=-cR;}
            if(R<0.0f){R=0.0f; cR=-cR;}
            if(G>1.0f){G=1.0f; cG=-cG;}
            if(G<0.0f){G=0.0f; cG=-cG;}
            if(B>1.0f){B=1.0f; cB=-cB;}
            if(B<0.0f){B=0.0f; cB=-cB;}
            return;
        }
}
}

void Adjust_Particles(){
    int p;
    for(p=0; p<MAX_PARTICLES; p++){
        // We move the speed towards the target speed by 1/20 (5%)
        Particles[p].sX+= (Particles[p].tX - Particles[p].sX) / 20.0f;
        Particles[p].sY+= (Particles[p].tY - Particles[p].sY) / 20.0f;
        Particles[p].sZ+= (Particles[p].tZ - Particles[p].sZ) / 20.0f;
        // Then we adjust the position of
        // the particle by the new speed
        Particles[p].X+= Particles[p].sX;
        Particles[p].Y+= Particles[p].sY;
        Particles[p].Z+= Particles[p].sZ;
        // Now for the bounce code.
        if(Particles[p].Y < 0.0f){
            Particles[p].Y = 0.0f;
            Particles[p].sY = -Particles[p].sY;
            Particles[p].BounceCount++;
            if(Particles[p].BounceCount > MAX_BOUNCE_COUNT){
                Particles[p].Active = FALSE;
            }
        }
        // And finally the age check
        Particles[p].Age++;
        if(Particles[p].Age > Particles[p].MaxAge){
            Particles[p].Active = FALSE;
        }
    }

}

void Render_Particles(){
    Activate_Particles();
    Adjust_Particles();

    glClear( GL_COLOR_BUFFER_BIT );

    int p;
    // Enable textures and bind our particle texture
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D, txParticle);
    // Disable Depth testing.
    glDisable(GL_DEPTH_TEST);
    // Enable blending
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_COLOR,GL_ONE);
    for(p=0; p<MAX_PARTICLES; p++){
        if(Particles[p].Active){
            glColor4f(Particles[p].R,
                Particles[p].G,
                Particles[p].B, 1.0f);
            glPushMatrix();
            glTranslatef(Particles[p].X,
                Particles[p].Y,
                Particles[p].Z);
            glBegin(GL_QUADS);
            glNormal3f(0.0f, 0.0f, 1.0f);
            glTexCoord2f(0.0f, 0.0f);
            glVertex3f(-Size, -Size, 0.0f);
            glTexCoord2f(1.0f, 0.0f);
            glVertex3f(Size, -Size, 0.0f);
            glTexCoord2f(1.0f, 1.0f);
            glVertex3f(Size, Size, 0.0f);
            glTexCoord2f(0.0f, 1.0f);
            glVertex3f(-Size, Size, 0.0f);
            glEnd();
            glPopMatrix();


        }
    }
     glEnable(GL_DEPTH_TEST);
     glutSwapBuffers();
}

bool LoadBitmapTexture(char * FileName, GLuint &texid){
    HBITMAP hBMP; // Handle Of The Bitmap
    BITMAP BMP; // Bitmap Structure
    glGenTextures(1, &texid); // Create The Texture
    hBMP=(HBITMAP)LoadImage(GetModuleHandle(NULL),
        FileName,
        IMAGE_BITMAP, 0, 0,
        LR_CREATEDIBSECTION | LR_LOADFROMFILE
        );

    if (!hBMP) // Does The Bitmap Exist?
        return FALSE; // If Not Return False
    GetObject(hBMP, sizeof(BMP), &BMP); // Get The Object
    // hBMP: Handle To Graphics Object
    // sizeof(BMP): Size Of Buffer For Object Information
    // &BMP: Buffer For Object Information
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    // Pixel Storage Mode (Word Alignment / 4 Bytes)
    // Typical Texture Generation Using Data From The Bitmap
    glBindTexture(GL_TEXTURE_2D, texid);// Bind To The Texture ID
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
        GL_LINEAR); // Linear Min Filter
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
        GL_LINEAR); // Linear Mag Filter
    glTexImage2D(GL_TEXTURE_2D, 0, 3, BMP.bmWidth, BMP.bmHeight,
        0, GL_BGR_EXT, GL_UNSIGNED_BYTE, BMP.bmBits);
    DeleteObject(hBMP); // Delete The Object
    return TRUE; // Loading Was Successful
}
4

1 回答 1

1

可能是您没有清除深度缓冲区。

它不会影响任何粒子,因为您在渲染它们时禁用了深度测试,但是当您渲染平面时,深度测试已启用,并且由于尚未清除深度缓冲区,因此它有一个 spaz 并且不渲染飞机。

glClear(GL_DEPTH_BUFFER_BIT);

在渲染平面以清除深度缓冲区之前。

编辑:这一定是它-

你在打电话

glClear(GL_COLOR_BUFFER_BIT);

渲染飞机后。看看你的 DrawGLScene 函数:

Load_Plane(); // you are drawing the plane here
glPushMatrix();
glScalef(1.0f, -1.0f, 1.0f);
Render_Particles(); // this function calls "glClear( GL_COLOR_BUFFER_BIT );"
// so anything that you rendered before is now removed.
glPopMatrix();
Render_Particles(); // same goes for here.

解决方案是从 Render_Particles 函数中删除对 glClear 的调用,并将其添加到 DrawGLScene 的顶部:

(新的 DrawGLScene 代码)

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Load_Plane();
glPushMatrix();
glScalef(1.0f, -1.0f, 1.0f);
Render_Particles();
glPopMatrix();
Render_Particles();

编辑#2:

您在 Render_Particles 函数中调用 glutSwapBuffers。不要在那里调用它。在 DrawGLScene 结束时调用它:

于 2012-11-24T18:37:02.477 回答