【GLSL】Hello World in GLSL

來源:互聯網
上載者:User

 

*****************************************************************************************************************

         這是來自lightthouse3d的教程,在此拙劣的翻譯一下,完全是為了自己加深印象,若你不經意看見,請指正錯誤之處。這裡並非逐句翻譯,譯者只是試圖用更加容易理解的語句來代替原句。***********************************************************************************************************

GLSL 教程執行個體

HelloWorld in GLSL

 

這是GLSL的helloworld(譯者注:還記得我們剛學編程時,很多第一課例子名字就是helloworld),一個最小的著色器,完成最基本任務:頂點轉換和用單一色渲染物體。這裡介紹頂點和片元著色器。

 

頂點著色器

頂點著色器是用來轉換頂點的,下面將展示如何通過固定管線的等式進行頂點轉換的,在固定管線狀態下頂點轉換是用模型視圖矩陣和投影矩陣通過下面的等式轉換的。

vTrans = projection * modelview * incomingVertex

為了在GLSL下些這樣的轉換,必須訪問OpenGL狀態來擷取這兩個矩陣,正如前面提到的,部分OpenGL狀態在GLSL下是可以容易擷取的,比如上面提到的兩個矩陣,是通過預定義的uniform類型的變數聲明的,如下: 

  uniform mat4 gl_ModelViewMatrix;
uniform mat4 gl_ProjectionMatrix;

還有一個必須做的事情:訪問輸入的頂點。這些頂點是通過預定義的attribute類型變數一個個傳給頂點著色器的:  

                                                                             attribute vec4 gl_Vertex;

為了輸出轉換後的頂點的,著色器也定義了vec4的預定義變數 gl_Position。

根據上面我們可以寫一個簡單的著色器了,除了轉換頂點其他什麼也不做,這意味著其他功能都沒有做,比如光照計算。

頂點著色器代碼如下:

 

                   void main()
                     {   
            gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
                    }

 

上面的代碼中每個頂點都用投影矩陣乘以模型視圖矩陣是一種浪費,因為這些矩陣不會每個頂點都會變的,GLSL提供了一個衍生矩陣,叫做gl_ModelViewProjectionMatrix 是上面兩個矩陣乘積的結果。因此著色器代碼改為:

 

 

                   void main()
                     {   
                       gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
                    }

 

這兩個結果相同。這能保證與固定管線相同嗎?理論上會的。但在一些特變處理頂點的情況下可能會有所不同,比如在一些圖形卡的高最佳化操作以及一些特別的函數利用了頂點轉換,另外一個原因可能就是有限的資料精度,當計算在在不同的命令下完成時,由於有限的資料精度可能得到不同的計算結果。因此GLSL提供了一種完全與固定功能相同的方法:

 

                    void main()
                     {   
                       gl_Position = ftransform();
                    }

 

 

 

片元著色器

片元著色器也有一個預定義的變數來表示顏色:

  void main()
               {
                       gl_FragColor = vec4(0.4,0.4,0.8,1.0);
   }

 

例子原始碼:opengl2.0下

/
#include <stdio.h>
#include <stdlib.h>

#include <GL/glew.h>
#include <GL/glut.h>

#include "textfile.h"  //讀取頂點和片元著色器代碼的類

GLuint v,f,f2,p;
float lpos[4] = {1,0.5,1,0};

void changeSize(int w, int h) {

 // Prevent a divide by zero, when window is too short
 // (you cant make a window of zero width).
 if(h == 0)
  h = 1;

 float ratio = 1.0* w / h;

 // Reset the coordinate system before modifying
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 
 // Set the viewport to be the entire window
    glViewport(0, 0, w, h);

 // Set the correct perspective.
 gluPerspective(45,ratio,1,1000);
 glMatrixMode(GL_MODELVIEW);

}
float a = 0;

void renderScene(void) {

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 glLoadIdentity();
 gluLookAt(0.0,0.0,5.0,
        0.0,0.0,-1.0,
     0.0f,1.0f,0.0f);

 glLightfv(GL_LIGHT0, GL_POSITION, lpos);
 glRotatef(a,0,1,1);
 glutSolidTeapot(1);
 a+=0.1;

 glutSwapBuffers();
}

void processNormalKeys(unsigned char key, int x, int y) {

 if (key == 27)
  exit(0);
}

#define printOpenGLError() printOglError(__FILE__, __LINE__)

int printOglError(char *file, int line)
{
    //
    // Returns 1 if an OpenGL error occurred, 0 otherwise.
    //
    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 printShaderInfoLog(GLuint obj)
{
    int infologLength = 0;
    int charsWritten  = 0;
    char *infoLog;

 glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

    if (infologLength > 0)
    {
        infoLog = (char *)malloc(infologLength);
        glGetShaderInfoLog(obj, infologLength, &charsWritten, infoLog);
  printf("%s/n",infoLog);
        free(infoLog);
    }
}

void printProgramInfoLog(GLuint obj)
{
    int infologLength = 0;
    int charsWritten  = 0;
    char *infoLog;

 glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infologLength);

    if (infologLength > 0)
    {
        infoLog = (char *)malloc(infologLength);
        glGetProgramInfoLog(obj, infologLength, &charsWritten, infoLog);
  printf("%s/n",infoLog);
        free(infoLog);
    }
}

 

void setShaders() {

 char *vs = NULL,*fs = NULL,*fs2 = NULL;

 v = glCreateShader(GL_VERTEX_SHADER);
 f = glCreateShader(GL_FRAGMENT_SHADER);
 f2 = glCreateShader(GL_FRAGMENT_SHADER);

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

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

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

 free(vs);free(fs);

 glCompileShader(v);
 glCompileShader(f);

 printShaderInfoLog(v);
 printShaderInfoLog(f);
 printShaderInfoLog(f2);

 p = glCreateProgram();
 glAttachShader(p,v);
 glAttachShader(p,f);

 glLinkProgram(p);
 printProgramInfoLog(p);

 glUseProgram(p);

}

 

int main(int argc, char **argv) {
 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
 glutInitWindowPosition(100,100);
 glutInitWindowSize(320,320);
 glutCreateWindow("MM 2004-05");

 glutDisplayFunc(renderScene);
 glutIdleFunc(renderScene);
 glutReshapeFunc(changeSize);
 glutKeyboardFunc(processNormalKeys);

 glEnable(GL_DEPTH_TEST);
 glClearColor(1.0,1.0,1.0,1.0);
 glEnable(GL_CULL_FACE);

 glewInit();
 if (glewIsSupported("GL_VERSION_2_0"))
  printf("Ready for OpenGL 2.0/n");
 else {
  printf("OpenGL 2.0 not supported/n");
  exit(1);
 }

 //setShaders();

 glutMainLoop();

 return 0;
}

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.