GLSL学习-波浪立方体

本文介绍了一个使用GLSL编程实现带有波浪效果的立方体示例。通过加载纹理,设置顶点、纹理坐标和法线,结合GLSL着色器在OpenGL环境中创建动态变化的立方体。GLSL着色器包括顶点和片段着色器,分别处理顶点变换和光照计算,实现纹理混合和波浪效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//CPP file

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <GL/glew.h>
#include <GL/glut.h>

float vertexArray[50][50*4*3];
float textureArray[50][50*4*2];
float normalArray[50][50*4*3];

#define BMP_Header_Length 54
GLuint loadTexture(char *file)
{
    GLint width, height, total_bytes;
    GLubyte* pixels = 0;
    GLuint last_texture_ID, texture_ID = 0;

    //打开文件,如果失败,返回
    FILE* pFile = fopen(file, "rb");
    if(pFile == 0)
    {
        printf("Can not open file %s...", file);
        return 0;
    }

    //读取文件中图象的宽度和高度
    fseek(pFile, 0x0012, SEEK_SET);
    fread(&width, 4, 1, pFile);
    fread(&height, 4, 1, pFile);
    fseek(pFile, BMP_Header_Length, SEEK_SET);

    //计算每行像素所占字节数,并根据此数据计算总像素字节数
    {
        GLint line_bytes = width * 3;
        while(line_bytes % 4 != 0)
        {
            ++line_bytes;
        }
        total_bytes = line_bytes * height;
    }

    //根据总像素字节数分配内存
    pixels = (GLubyte*)malloc(total_bytes);
    if(pixels == 0)
    {
        printf("Pixeles in file %s is NULL...", file);
        fclose(pFile);
        return 0;
    }

    //读取像素数据
    if(fread(pixels, total_bytes, 1, pFile) <= 0)
    {
        free(pixels);
        fclose(pFile);
        return 0;
    }

    // 分配一个新的纹理编号
    glGenTextures(1, &texture_ID);
    if( texture_ID == 0 )
     {
        free(pixels);
        fclose(pFile);
        return 0;
     }

    //绑定新的纹理,载入纹理并设置纹理参数
    //在绑定前,先获得原来绑定的纹理编号,以便在最后进行恢复
    glGetIntegerv(GL_TEXTURE_BINDING_2D,(GLint*)&last_texture_ID);
    glBindTexture(GL_TEXTURE_2D, texture_ID);

    //纹理过滤设定
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

    //颜色混合模式
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
    glBindTexture(GL_TEXTURE_2D, last_texture_ID);

    //之前为pixels分配的内存可在使用glTexImage2D以后释放
    //因为此时像素数据已经被OpenGL另行保存了一份(可能被保存到专门的图形硬件中)
    free(pixels);
    return texture_ID;
}

int texture01 = 0;
int texture02 = 0;
void setupRS()
{
    glClearColor(0.0f,0.0f,0.0f,1.0f);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_BLEND);
    glEnable(GL_TEXTURE_2D);
    texture01 = loadTexture("../../Resources/texture01.bmp");
    texture02 = loadTexture("../../Resources/texture02.bmp");
}

#define printOpenGLError() printOglError(__FILE__, __LINE__)
int printOglError(char *file, int line)
{
    GLenum glErr;
    int retCode = 0;
    
    glErr = glGetError();
    while (glErr != GL_NO_ERROR)
    {
        printf("glError in file %s @line %d: %s.\n", file, line, gluErrorString(glErr));
        retCode = 1;
        glErr = glGetError();
    }
    return retCode;
}


void printInfoLog(GLhandleARB obj)
{
    int infologLength = 0;
    int charsWritten  = 0;
    char *infoLog;

    glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
                                         &infologLength);
    if (infologLength > 0)
    {
        infoLog = (char *)malloc(infologLength);
        glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
        printf("%s.\n",infoLog);
        free(infoLog);
    }
}

char *textFileRead(char *fn)
{
    FILE *fp;
    char *content = NULL;
    int count=0;
    if (fn != NULL) {
        fp = fopen(fn, "rt");
        if (fp != NULL) {
            fseek(fp, 0, SEEK_END);
            count = ftell(fp);
            rewind(fp);
            if (count > 0) {
                content = (char *)malloc(sizeof(char) * (count+1));
                count = fread(content,sizeof(char),count,fp);
                content[count] = '\0';
            }
            fclose(fp);                            
        }
    }
    return content;
}

GLhandleARB v,f,p;    //Handlers for our vertex, geometry, and fragment shaders
int gw,gh;        //Keep track of window width and height
GLint loc;
void setShaders()
{
    glClearColor(0.0f,0.0f,0.0f,1.0f);
    glEnable(GL_DEPTH_TEST);

    char *vs = NULL,*fs = NULL;
    v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
    f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

    vs = textFileRead("MyTest.vert");
    fs = textFileRead("MyTest.frag");

    const char * vv = vs;
    const char * ff = fs;

    glShaderSourceARB(v, 1, &vv,NULL);
    glShaderSourceARB(f, 1, &ff,NULL);

    free(vs);
    free(fs);
    
    glCompileShaderARB(v);
    glCompileShaderARB(f);

    printInfoLog(v);
    printInfoLog(f);

    p = glCreateProgramObjectARB();

    glAttachObjectARB(p,v);
    glAttachObjectARB(p,f);

    glLinkProgramARB(p);
    printInfoLog(p);

    glUseProgramObjectARB(p);

    printInfoLog(v);
    printInfoLog(f);
    printInfoLog(p);
    
    glUniform3fARB(glGetUniformLocationARB(p, "LightPosition"), 200.0f, 200.0f, 200.0f);
    glUniform1iARB(glGetUniformLocationARB(p, "tex01"), 0);
    glUniform1iARB(glGetUniformLocationARB(p, "tex02"), 1);
    loc = glGetUniformLocation(p,"time");
}

void reshape(int w, int h)
{
    float range = 50.0f;
    if (0 == h)
        h = 1;
    glViewport(0,0,w,h);

    float as = (float)w/h;
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    /*if (w <= h)
        glOrtho(-range, range, -range/as, range/as, -range, range);
    else
        glOrtho(-range*as, range*as, -range, range, -range, range);*/
    
    gluPerspective(100.0f, as, 1, 150);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void setXYZ(float *vector, int offset, float x, float y, float z)
{
    int index = 3 * offset;
    vector[index] = x;
    vector[index + 1] = y;
    vector[index + 2] = z;
}
    
void setXY(float *vector, int offset, float x, float y)
{
    int index = 2 * offset;
    vector[index] = x;
    vector[index + 1] = y;
}

void initQuad(float width, float height)
{
    const float halfW = width/2.0f;
    const float halfH = height/2.0f;

    const float deltaW = width/50;
    const float deltaH = height/50;

    for (int i = 0; i < 50; ++i)
    {
        float verX = -halfW + deltaW*i;
        float verX_next = -halfW + deltaW*(i+1);

        float coorX = (float)i/50;
        float coorX_next = (float)(i+1)/50;
        for (int j = 0; j < 50; ++j)
        {
            float verY = -halfH + deltaH*j;
            float verY_next = -halfH + deltaH*(j+1);

            float coorY = (float)j/50;
            float coorY_next = (float)(j+1)/50;

            setXYZ(vertexArray[i], j*4, verX, verY, 0.0f);
            setXYZ(vertexArray[i], j*4+1, verX_next, verY, 0.0f);
            setXYZ(vertexArray[i], j*4+2, verX_next, verY_next, 0.0f);
            setXYZ(vertexArray[i], j*4+3, verX, verY_next, 0.0f);

            setXYZ(normalArray[i], j*4, 0.0f, 0.0f, 1.0f);
            setXYZ(normalArray[i], j*4+1, 0.0f, 0.0f, 1.0f);
            setXYZ(normalArray[i], j*4+2, 0.0f, 0.0f, 1.0f);
            setXYZ(normalArray[i], j*4+3, 0.0f, 0.0f, 1.0f);

            setXY(textureArray[i], j*4, coorX, coorY);
            setXY(textureArray[i], j*4+1, coorX_next, coorY);
            setXY(textureArray[i], j*4+2, coorX_next, coorY_next);
            setXY(textureArray[i], j*4+3, coorX, coorY_next);
        }
    }
}

void draw()
{
    for (int i = 0; i < 50; i++)
    {
        glVertexPointer(3, GL_FLOAT, 0, vertexArray[i]);
        glTexCoordPointer(2, GL_FLOAT, 0, textureArray[i]);
        glNormalPointer(GL_FLOAT, 0, normalArray[i]);
        //glDrawArrays(GL_POINTS, 0, 50*4);
        glDrawArrays(GL_QUADS, 0, 50*4);
    }
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glEnableClientState(GL_NORMAL_ARRAY);
}

float angle = 0.0f;
float t = 0.0f;
void display()
{
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glColor4f(1.0f,1.0f,0.0f,1.0f);
    //glBlendFunc(GL_SRC_ALPHA, GL_ONE);

    glUseProgram(p);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture01);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture02);

    glLoadIdentity();
    glTranslatef(0.0f,0.0f, -100.0f);

    glPushMatrix();
    glRotatef(angle, 1.0f, 1.0f,1.0f);
    glPushMatrix();
    glTranslatef(0.0f,0.0f, 25.0f);
    draw();
    glPopMatrix();

    glPushMatrix();
    glRotatef(180.0f, 0.0f, 1.0f, 0.0f);
    glTranslatef(0.0f,0.0f, 25.0f);
    draw();
    glPopMatrix();

    glPushMatrix();
    glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
    glTranslatef(0.0f,0.0f, 25.0f);
    draw();
    glPopMatrix();

    glPushMatrix();
    glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
    glTranslatef(0.0f,0.0f, 25.0f);
    draw();
    glPopMatrix();

    glPushMatrix();
    glRotatef(90.0f, 1.0f, 0.0f, 0.0f);
    glTranslatef(0.0f,0.0f, 25.0f);
    draw();
    glPopMatrix();

    glPushMatrix();
    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
    glTranslatef(0.0f,0.0f, 25.0f);
    draw();
    glPopMatrix();

    glPopMatrix();

    glutSwapBuffers();
    glutPostRedisplay();

    angle += 0.5f;
    if (angle >= 360.0f)
    {
        angle -= 360.0f;
    }

    glUniform1f(loc, t);
    t += 0.1f;
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH|GLUT_RGBA);
    glutInitWindowSize(500, 500);
    glutInitWindowPosition(500,200);
    glutCreateWindow("<<-- My Test -->>");
    
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    
    setupRS();
    initQuad(50.0f, 50.0f);

    glewInit();
    if (glewIsSupported("GL_VERSION_2_1"))
    {
        printf("Ready for OpenGL 2.1\n");
    }
    else
    {
        printf("OpenGL 2.1 not supported\n");
        exit(1);
    }
    if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader && GL_EXT_geometry_shader4)
    {
        printf("Ready for GLSL - vertex, fragment, and geometry units\n");
    }
    else
    {
        printf("Not totally ready :( \n");
        exit(1);
    }

    setShaders();

    glutMainLoop();
    return 0;
}

//MyTest.vert

varying vec3 lightDir,normal;
uniform float time;

void main()  
{  
    normal = normalize(gl_NormalMatrix * gl_Normal);
    lightDir = normalize(vec3(gl_LightSource[0].position));

    gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;  
    //gl_Position = ftransform();  

    vec4 v = vec4(gl_Vertex);
    float temp = sqrt(pow(v.x,2)+pow(v.y,2));
    v.z = v.z + sin(5.0*temp+time)*2.0;

    //v.z = v.z + sin(5.0*v.x+time)*2.0;
    gl_Position = gl_ModelViewProjectionMatrix * v;
}

//MyTest.frag

varying vec3 lightDir,normal;
uniform sampler2D tex01, tex02;

void main()
{
    vec3 ct,cf,c;
    vec4 texel;
    float intensity,at,af,a;
    
    intensity = max(dot(lightDir,normalize(normal)),0.0);
    
    cf = intensity * (gl_FrontMaterial.diffuse).rgb + gl_FrontMaterial.ambient.rgb;
    af = gl_FrontMaterial.diffuse.a;
    texel = texture2D(tex01,gl_TexCoord[0].st);
        
    ct = texel.rgb;
    at = texel.a;
    
    c = cf * ct;
    a = af * at;
        
    float coef = smoothstep(1.0,0.2,intensity);
    c += coef *  vec3(texture2D(tex02,gl_TexCoord[0].st));
    
    gl_FragColor = vec4(c, a);    
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值