GLSL学习工过程中的代码——earth

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

//创建3个纹理对象
GLuint dayearth;
GLuint nightearth;
GLuint cloudsearth;
//创建二次对象
GLUquadricObj *qobj;
GLfloat xoffset = 0.0;
PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation;
PFNGLUNIFORM3FPROC glUniform3f;
PFNGLUNIFORM1IPROC glUniform1i;
PFNGLACTIVETEXTUREPROC glActiveTexture;

#define printOpenGLError() printOglError(__FILE__, __LINE__)

#define BMP_Header_Length 54
GLuint loadTexture(char *file)
{
    GLint width, height,totalBytes;
    GLubyte* pixels = 0;
    GLuint textureID = 0;
    GLint lineByte;
    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);
    lineByte = width * 3;
    
    while( lineByte % 4 != 0 )
    {
        ++lineByte;
    }
    totalBytes = lineByte * height;
    pixels = (GLubyte*)malloc(totalBytes);
    if ( pixels == 0 ) {
        fclose(pFile);
        return 0;
    }

    if ( fread(pixels, totalBytes, 1, pFile) <= 0 ) {
        free(pixels);
        fclose(pFile);
        return 0;
    }

    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    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);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);

    free(pixels);
    fclose(pFile);
    return textureID;
}

/**
* @brief 打印OpenGL错误信息
* @param  file 错误所在的文件
* @param  line 错误所在的行
* @return 1 OpenGL error
* @return 0 other  error
**/
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;
}

/**
* @brief 打印日志
**/
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;
    }

//YEAH, YEAH, YEAH ... global vars, this is a freggn demo!
GLhandleARB v,f,p;            //Handlers for our vertex, geometry, and fragment shaders
int gw,gh;                //Keep track of window width and height
    
void setShaders()
{
    glClearColor(0.0f,0.0f,0.0f,1.0f);
    glEnable(GL_DEPTH_TEST);

    //分别载入地球的白天,夜晚,云彩光泽纹理
    dayearth = loadTexture("Day.bmp");
    nightearth = loadTexture("Night.bmp");
    cloudsearth = loadTexture("Clouds.bmp");

    glUniform3f = (PFNGLUNIFORM3FPROC)wglGetProcAddress("glUniform3f");
    glUniform1i = (PFNGLUNIFORM1IPROC)wglGetProcAddress("glUniform1i");
    glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)wglGetProcAddress ("glGetUniformLocation");
    glActiveTexture = (PFNGLACTIVETEXTUREPROC)wglGetProcAddress("glActiveTexture");

    char *vs = NULL,*fs = NULL;
    ///创造空白顶点着色器对象并返回其句柄
    v = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);   ///顶点着色器 v
    f = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); ///片元着色器 f

    ///读取着色器源代码文件
    vs = textFileRead("Earth.vert");///顶点着色器源代码字符串
    fs = textFileRead("Earth.frag");///片元着色器源代码字符串

    ///加入到字符串数组
    const char * vv = vs;
    const char * ff = fs;

    /// 将着色器源代码字符串数组提交给空白的着色器
    /// glShaderSourceARB() 参数表:
    /// GLhandleARB shader        --- 着色器
    /// GLuint nstrings           --- 字符串数组中多少个元素 本例子就只有1个字符串
    /// const GLcharARB **strings --- 字符串数组
    /// GLint *lengths            --- 对应字符串数组的长度数组 NULL表示所有字符串以null结束
    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);
        
    glUniform3f(glGetUniformLocation(p, "LightPosition"), 4.0, 0.0, 0.0 );

    //设置纹理单元的一致变量,这里要用glUniform1i
    glUniform1i(glGetUniformLocation(p, "EarthDay"), 0 );
    glUniform1i(glGetUniformLocation(p, "EarthNight"), 1 );
    glUniform1i(glGetUniformLocation(p, "EarthCloudGloss"), 2 );
}

void reshape(int w, int h)
{
    float range = 200.0f;

    if (0 == h)
        h = 1;

    glViewport(0,0, w,h);

    float aspect = (float)w/h;

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    if (w <= h)
        glOrtho(-range, range, -range/aspect, range/aspect, -range, range);
    else
        glOrtho(-range*aspect, range*aspect, -range, range, -range, range);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

void display(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(p);

    //把白天的活动纹理单元设置为纹理单元0
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, dayearth);
    //把夜晚的活动纹理单元设置为纹理单元1
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, nightearth);
    //把云彩光泽的活动纹理单元设置为纹理单元2
    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D, cloudsearth);

    //利用二次对象画球,这里使用函数gluSolidSphere画球不行
    //因为我们需要为每个顶点指定一个表面法线和一个2D纹理坐标
    qobj = gluNewQuadric();
    gluQuadricDrawStyle(qobj, GLU_FILL);
    gluQuadricNormals(qobj, GLU_SMOOTH);
    gluQuadricTexture(qobj, GL_TRUE);

    glPushMatrix();
    //glTranslated(0.0, 0.0, -4.0);
    //使地球沿Y轴旋转
    glRotatef(xoffset, 1.0, 1.0, 1.0);
    gluSphere(qobj, 100.0f, 50, 50);
    glPopMatrix();
    glutSwapBuffers();
    glutPostRedisplay();
    
    xoffset += 0.02f;
    if (xoffset >= 360.0f)
    {
        xoffset -= 360.0f;
    }
}

int main(int argc, char* argv[])
{
    //初始化GLUT并运行
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowPosition(100, 100);
    glutInitWindowSize(600, 600);
    glutCreateWindow("Read bmp");
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    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;
}


//Earth.vert

varying float Diffuse;
varying vec3 Specular;
varying vec2 TexCoord;

uniform vec3 LightPosition;

void main(void)
{
    vec3 ecPosition = vec3 (gl_ModelViewMatrix * gl_Vertex);
    vec3 tnorm      = normalize(gl_NormalMatrix * gl_Normal);
    vec3 lightVec   = normalize(LightPosition - ecPosition);
    vec3 reflectVec = reflect(-lightVec, tnorm);
    vec3 viewVec    = normalize(-ecPosition);

    float spec      = clamp(dot(reflectVec, viewVec), 0.0, 1.0);
    spec            = pow(spec, 8.0);
    Specular        = vec3 (spec) * vec3 (1.0, 0.941, 0.898) * 0.3;

    Diffuse         = max(dot(lightVec, tnorm), 0.0);

    TexCoord        = gl_MultiTexCoord0.st;
    gl_Position     = ftransform();
}


//Earth.frag

uniform sampler2D EarthDay;

uniform sampler2D EarthNight;
uniform sampler2D EarthCloudGloss;

varying float Diffuse;
varying vec3 Specular;
varying vec2 TexCoord;

void main (void)
{
     vec2 clouds    = texture2D(EarthCloudGloss, TexCoord).rg;
    vec3 daytime   = (texture2D(EarthDay, TexCoord).rgb * Diffuse +
                          Specular * clouds.g) * (1.0 - clouds.r) +
                          clouds.r * Diffuse;
    vec3 nighttime = texture2D(EarthNight, TexCoord).rgb *
                         (1.0 - clouds.r) * 2.0;

    vec3 color = daytime;

    if (Diffuse <= 0.1)
        color = mix(nighttime, daytime, (Diffuse + 0.1) * 5.0);

    gl_FragColor = vec4 (color, 1.0);

}


调试结果如下



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值