Grafikprogrammierung
OpenGL Shading Language (GLSL)
Thorsten Thormählen
06. Dezember 2024
Teil 9, Kapitel 1
Thorsten Thormählen
06. Dezember 2024
Teil 9, Kapitel 1
Dies ist die Druck-Ansicht.
Weiterschalten der Folien durch die → Taste oder
durch das Klicken auf den rechten Folienrand.
Das Weiterschalten der Folien kann ebenfalls durch das Klicken auf den rechten bzw. linken Folienrand erfolgen.
Typ | Schriftart | Beispiele |
---|---|---|
Variablen (Skalare) | kursiv | $a, b, x, y$ |
Funktionen | aufrecht | $\mathrm{f}, \mathrm{g}(x), \mathrm{max}(x)$ |
Vektoren | fett, Elemente zeilenweise | $\mathbf{a}, \mathbf{b}= \begin{pmatrix}x\\y\end{pmatrix} = (x, y)^\top,$ $\mathbf{B}=(x, y, z)^\top$ |
Matrizen | Schreibmaschine | $\mathtt{A}, \mathtt{B}= \begin{bmatrix}a & b\\c & d\end{bmatrix}$ |
Mengen | kalligrafisch | $\mathcal{A}, B=\{a, b\}, b \in \mathcal{B}$ |
Zahlenbereiche, Koordinatenräume | doppelt gestrichen | $\mathbb{N}, \mathbb{Z}, \mathbb{R}^2, \mathbb{R}^3$ |
progID = glCreateProgram();
vertID = glCreateShader(GL_VERTEX_SHADER); fragID = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(vertID, 1, &vertShaderSrcCodeString, &vStrLength); glShaderSource(fragID, 1, &fragShaderSrcCodeString, &fStrLength); glCompileShader(vertID); glCompileShader(fragID);
glAttachShader(progID, vertID); glAttachShader(progID, fragID); glLinkProgram(progID);
glUseProgram(progID);
glDeleteProgram(progID); glDeleteShader(vertID); glDeleteShader(fragID);
float, vec2, vec3, vec4, mat2, mat3, mat4
int, ivec2, ivec3, ivec4, uint, uvec2, uvec3, uvec4
bool, bvec2, bvec3, bvec4
sampler2D, sampler3D, samplerCube, ...
struct Vertex { float val1; int val2; bool val3; };
float a[16];
float a = float(1);
if, if()else
for, while, do{}while()
return, break, continue
byte, short, long
-Typen, Kein union
switch()case
// construction vec2 a = vec2(1.0, 2.0); vec3 b = vec3(1.0,-1.0, 1.0); vec4 c = vec4(1.0, 2.0, 3.0, 4.0); vec4 allOne = vec4(1.0); vec4 d = vec4(a, a); vec4 e = vec4(b, 1.0); // accessing elements float f = b[1]; // is -1.0 float g = b.y; // is -1.0 as well //conversion d = c.rgba; // stays a 4-vector b = c.xyz; // convert to 3-vector a = c.xy; // convert to 2-vector e = c.xxyy; // e = (1.0, 1.0, 2.0, 2.0) "swizzling" e.xz = vec2(0.5, 0.6); // e = (0.5, 1.0, 0.6, 2.0)
// construction mat4 a = mat4(0.0, 0.1, 0.2, 0.3, // column major order: 0.4, 0.5, 0.6, 0.7, // transposed of the 0.8, 0.9, 1.0, 1.1, // usual interpretation 1.2, 1.3, 1.4, 1.5); mat3 b = mat3(1.0); // identity matrix // conversion mat3 c = mat3(a); // upper 3x3 matrix vec4 d = a[1]; // d = (0.4, 0.5, 0.6, 0.7) // operations vec4 e = a * vec4(1.0); mat4 f = 2.0 * a - mat4(1.0);
class Renderer { private: struct Vertex { float position[3]; float color[4]; }; private: enum {Triangle, numVAOs}; enum {TriangleAll, numVBOs}; GLuint vaoID[numVAOs]; GLuint bufID[numVBOs]; int triangleVertNo; GLuint progID; GLuint vertID; GLuint fragID; GLint vertexLoc; GLint colorLoc; public: // constructor Renderer() : triangleVertNo(0), progID(0), vertID(0), fragID(0), vertexLoc(-1), colorLoc(-1) {} //destructor ~Renderer() { glDeleteVertexArrays(numVAOs, vaoID); glDeleteBuffers(numVBOs, bufID); glDeleteProgram(progID); glDeleteShader(vertID); glDeleteShader(fragID); } public: void init() { initExtensions(); glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH); setupShaders(); // create a Vertex Array Objects (VAO) glGenVertexArrays(numVAOs, vaoID); // generate a Vertex Buffer Object (VBO) glGenBuffers(numVBOs, bufID); // binding the Triangle VAO glBindVertexArray(vaoID[Triangle]); float triangleVertexData[] = { 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, -0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.5f,-0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, }; triangleVertNo = 3; glBindBuffer(GL_ARRAY_BUFFER, bufID[TriangleAll]); glBufferData(GL_ARRAY_BUFFER, triangleVertNo*sizeof(Vertex), triangleVertexData, GL_STATIC_DRAW); int stride = sizeof(Vertex); char *offset = (char*)NULL; // position if(vertexLoc != -1) { glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(vertexLoc); } // color if(colorLoc != -1) { offset = (char*)NULL + 3*sizeof(float); glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(colorLoc); } } void setupShaders() { // create shader vertID = glCreateShader(GL_VERTEX_SHADER); fragID = glCreateShader(GL_FRAGMENT_SHADER); // load shader source from file std::string vs = loadShaderSrc("./first.vert"); const char* vss = vs.c_str(); std::string fs = loadShaderSrc("./first.frag"); const char* fss = fs.c_str(); // specify shader source glShaderSource(vertID, 1, &(vss), NULL); glShaderSource(fragID, 1, &(fss), NULL); // compile the shader glCompileShader(vertID); glCompileShader(fragID); // check for errors printShaderInfoLog(vertID); printShaderInfoLog(fragID); // create program and attach shaders progID = glCreateProgram(); glAttachShader(progID, vertID); glAttachShader(progID, fragID); // "outColor" is a user-provided OUT variable // of the fragment shader. // Its output is bound to the first color buffer // in the framebuffer glBindFragDataLocation(progID, 0, "outputColor"); // link the program glLinkProgram(progID); // output error messages printProgramInfoLog(progID); // "inputPosition" and "inputColor" are user-provided // IN variables of the vertex shader. // Their locations are stored to be used later with // glEnableVertexAttribArray() vertexLoc = glGetAttribLocation(progID,"inputPosition"); colorLoc = glGetAttribLocation(progID, "inputColor"); } void resize(int w, int h) { glViewport(0, 0, w, h); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glUseProgram(progID); // bind Triangle VAO glBindVertexArray(vaoID[Triangle]); // render data glDrawArrays(GL_TRIANGLES, 0, triangleVertNo); } private: void printShaderInfoLog(GLuint obj) { int infoLogLength = 0; int returnLength = 0; char *infoLog; glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength); if (infoLogLength > 0) { infoLog = (char *)malloc(infoLogLength); glGetShaderInfoLog(obj, infoLogLength, &returnLength, infoLog); printf("%s\n",infoLog); free(infoLog); } } void printProgramInfoLog(GLuint obj) { int infoLogLength = 0; int returnLength = 0; char *infoLog; glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength); if (infoLogLength > 0) { infoLog = (char *)malloc(infoLogLength); glGetProgramInfoLog(obj, infoLogLength, &returnLength, infoLog); printf("%s\n",infoLog); free(infoLog); } } std::string loadShaderSrc(const std::string& filename) { std::ifstream is(filename); if (is.is_open()) { std::stringstream buffer; buffer << is.rdbuf(); return buffer.str(); } cerr << "Unable to open file " << filename << endl; exit(1); } };
#version 140 in vec3 inputPosition; in vec4 inputColor; out vec3 forFragColor; void main(){ forFragColor = inputColor.rgb; gl_Position = vec4(inputPosition, 1.0); }
#version 140 in vec3 forFragColor; out vec4 outputColor; void main() { outputColor = vec4(forFragColor,1.0); }
in
-Variablen übergeben werden
in
-Variablen, die automatisch erzeugt werden, und benutzerdefinierte in
-Variablen,
die von der Applikation übergeben werden müssen
Um Daten eines VBOs für die benutzerdefinierten
in
-Variablen zu verwenden, wird häufig wie folgt vorgegangen
glGetAttribLocation
wird ein Lokalisierungskennzeichner für eine in
-Variable abgefragt. Heißt die Variable
im Shader-Code beispielsweise "inputColor" int colorLoc = glGetAttribLocation(progID, "inputColor");
glVertexAttribPointer(colorLoc, size, type, normalized, stride, offset)
definiert dann die Zuordnung zwischen in
-Variable
und VBO-Daten
glEnableVertexAttribArray(colorLoc);
glDrawArray
bzw. glDrawElements
mit aktiviertem VBO werden die in
-Variable
des Vertex-Shaders dann für jedes gezeichnete Vertex entsprechend gefüllt
out
-Variablen des Vertex-Shaders werden im Rasterisierer interpoliert und die interpolierten Werte als in
-Variablen
im Fragment-Shader zur Verfügung gestellt
out
-Variablen des Fragmentshaders werden zum Framebuffer geschickt
out
-Variable "outputColor" in den ersten Color-Buffer des Framebuffers geschrieben werden, kann dies
erreicht werden durch glBindFragDataLocation(progID, 0, "outputColor");
in
-Variablen sind uniform
-Variablen eine weitere Möglichkeit, um Daten an einen Shader zu übergeben
in
-Variablen, die Vertex Attribute beschreiben, beinhalten die uniform
-Variablen Daten, die
für alle gezeichneten Stützpunte eines glDrawArray
bzw. glDrawElements
-Aufrufs konstant sind
uniform
-Variablen kann abgefragt werden durch paraLoc = glGetUniformLocation(progID, "parameter");
uniform
-Variable folgendermaßen gesetzt werden
glUniform1i(paraLoc, 123);
glUniform3fv(threeVectorLoc, 1, threeVector);
glUniformMatrix4fv(modelviewLoc, 1, transpose, modelview);
uniform
-Variablen übergeben und damit die
Funktionalität der aus der Fixed-Function Pipeline bekannten GL_MODELVIEW
und GL_PROJECTION
Matrizen im Shader simuliert
class Renderer { private: struct Vertex { float position[3]; float color[4]; }; public: float t; private: enum {Triangle, numVAOs}; enum {TriangleAll, numVBOs}; GLuint vaoID[numVAOs]; GLuint bufID[numVBOs]; int triangleVertNo; GLuint progID; GLuint vertID; GLuint fragID; GLuint vertexLoc; GLuint colorLoc; GLuint projectionLoc; GLuint modelviewLoc; float projection[16]; // projection matrix float modelview[16]; // modelview matrix public: // constructor Renderer() : t(0.0f), triangleVertNo(0), progID(0), vertID(0), fragID(0), vertexLoc(-1), colorLoc(-1), projectionLoc(-1), modelviewLoc(-1) {} //destructor ~Renderer() { glDeleteVertexArrays(numVAOs, vaoID); glDeleteBuffers(numVBOs, bufID); glDeleteProgram(progID); glDeleteShader(vertID); glDeleteShader(fragID); } public: void init() { initExtensions(); glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH); setupShaders(); // create a Vertex Array Objects (VAO) glGenVertexArrays(numVAOs, vaoID); // generate a Vertex Buffer Object (VBO) glGenBuffers(numVBOs, bufID); // binding the Triangle VAO glBindVertexArray(vaoID[Triangle]); float triangleVertexData[] = { 0.0f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, -0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.5f,-0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, }; triangleVertNo = 3; glBindBuffer(GL_ARRAY_BUFFER, bufID[TriangleAll]); glBufferData(GL_ARRAY_BUFFER, triangleVertNo*sizeof(Vertex), triangleVertexData, GL_STATIC_DRAW); int stride = sizeof(Vertex); char *offset = (char*)NULL; // position if(vertexLoc != -1) { glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(vertexLoc); } // color if(colorLoc != -1) { offset = (char*)NULL + 3*sizeof(float); glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(colorLoc); } } void setupShaders() { // create shader vertID = glCreateShader(GL_VERTEX_SHADER); fragID = glCreateShader(GL_FRAGMENT_SHADER); // load shader source from file std::string vs = loadShaderSrc("./uniform.vert"); const char* vss = vs.c_str(); std::string fs = loadShaderSrc("./uniform.frag"); const char* fss = fs.c_str(); // specify shader source glShaderSource(vertID, 1, &(vss), NULL); glShaderSource(fragID, 1, &(fss), NULL); // compile the shader glCompileShader(vertID); glCompileShader(fragID); // check for errors printShaderInfoLog(vertID); printShaderInfoLog(fragID); // create program and attach shaders progID = glCreateProgram(); glAttachShader(progID, vertID); glAttachShader(progID, fragID); // "outColor" is a user-provided OUT variable // of the fragment shader. // Its output is bound to the first color buffer // in the framebuffer glBindFragDataLocation(progID, 0, "outputColor"); // link the program glLinkProgram(progID); // output error messages printProgramInfoLog(progID); // "inputPosition" and "inputColor" are user-provided // IN variables of the vertex shader. // Their locations are stored to be used later with // glEnableVertexAttribArray() vertexLoc = glGetAttribLocation(progID,"inputPosition"); colorLoc = glGetAttribLocation(progID, "inputColor"); // "projection" and "modelview" are user-provided // UNIFORM variables of the vertex shader. // Their locations are stored to be used later projectionLoc = glGetUniformLocation(progID, "projection"); modelviewLoc = glGetUniformLocation(progID, "modelview"); } void resize(int w, int h) { glViewport(0, 0, w, h); // this function replaces gluPerspective mat4Perspective(projection, 45.0f, (float)w/(float)h, 0.5f, 4.0f); //mat4Print(projection); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // camera orbits in the y=2 plane // and looks at the origin // mat4LookAt replaces gluLookAt double rad = M_PI / 180.0f * t; mat4LookAt(modelview, 2.0f*cos(rad), 2.0f, 2.0f*sin(rad), // eye 0.0f, 0.0f, 0.0f, // look at 0.0f, 1.0f, 0.0f); // up glUseProgram(progID); // load the current projection and modelview matrix into the // corresponding UNIFORM variables of the shader glUniformMatrix4fv(projectionLoc, 1, false, projection); glUniformMatrix4fv(modelviewLoc, 1, false, modelview); // bind Triangle VAO glBindVertexArray(vaoID[Triangle]); // render data glDrawArrays(GL_TRIANGLES, 0, triangleVertNo); } private: void printShaderInfoLog(GLuint obj) { int infoLogLength = 0; int returnLength = 0; char *infoLog; glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength); if (infoLogLength > 0) { infoLog = (char *)malloc(infoLogLength); glGetShaderInfoLog(obj, infoLogLength, &returnLength, infoLog); printf("%s\n",infoLog); free(infoLog); } } void printProgramInfoLog(GLuint obj) { int infoLogLength = 0; int returnLength = 0; char *infoLog; glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength); if (infoLogLength > 0) { infoLog = (char *)malloc(infoLogLength); glGetProgramInfoLog(obj, infoLogLength, &returnLength, infoLog); printf("%s\n",infoLog); free(infoLog); } } std::string loadShaderSrc(const std::string& filename) { std::ifstream is(filename); if (is.is_open()) { std::stringstream buffer; buffer << is.rdbuf(); return buffer.str(); } cerr << "Unable to open file " << filename << endl; exit(1); } // the following functions are some matrix and vector helpers // they work for this demo but in general it is recommended // to use more advanced matrix libraries, // e.g. OpenGL Mathematics (GLM) float vec3Dot( float *a, float *b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; } void vec3Cross( float *a, float *b, float *res) { res[0] = a[1] * b[2] - b[1] * a[2]; res[1] = a[2] * b[0] - b[2] * a[0]; res[2] = a[0] * b[1] - b[0] * a[1]; } void vec3Normalize(float *a) { float mag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); a[0] /= mag; a[1] /= mag; a[2] /= mag; } void mat4Identity( float *a) { for (int i = 0; i < 16; ++i) a[i] = 0.0f; for (int i = 0; i < 4; ++i) a[i + i * 4] = 1.0f; } void mat4Multiply(float *a, float *b, float *res) { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { res[j*4 + i] = 0.0f; for (int k = 0; k < 4; ++k) { res[j*4 + i] += a[k*4 + i] * b[j*4 + k]; } } } } void mat4Perspective(float *a, float fov, float aspect, float zNear, float zFar) { float f = 1.0f / float(tan (fov/2.0f * (M_PI / 180.0f))); mat4Identity(a); a[0] = f / aspect; a[1 * 4 + 1] = f; a[2 * 4 + 2] = (zFar + zNear) / (zNear - zFar); a[3 * 4 + 2] = (2.0f * zFar * zNear) / (zNear - zFar); a[2 * 4 + 3] = -1.0f; a[3 * 4 + 3] = 0.0f; } void mat4LookAt(float *viewMatrix, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) { float dir[3], right[3], up[3], eye[3]; up[0]=upX; up[1]=upY; up[2]=upZ; eye[0]=eyeX; eye[1]=eyeY; eye[2]=eyeZ; dir[0]=centerX-eyeX; dir[1]=centerY-eyeY; dir[2]=centerZ-eyeZ; vec3Normalize(dir); vec3Cross(dir,up,right); vec3Normalize(right); vec3Cross(right,dir,up); vec3Normalize(up); // first row viewMatrix[0] = right[0]; viewMatrix[4] = right[1]; viewMatrix[8] = right[2]; viewMatrix[12] = -vec3Dot(right, eye); // second row viewMatrix[1] = up[0]; viewMatrix[5] = up[1]; viewMatrix[9] = up[2]; viewMatrix[13] = -vec3Dot(up, eye); // third row viewMatrix[2] = -dir[0]; viewMatrix[6] = -dir[1]; viewMatrix[10] = -dir[2]; viewMatrix[14] = vec3Dot(dir, eye); // forth row viewMatrix[3] = 0.0f; viewMatrix[7] = 0.0f; viewMatrix[11] = 0.0f; viewMatrix[15] = 1.0f; } void mat4Print(float* a) { // opengl uses column major order for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { cout << a[j * 4 + i] << " "; } cout << endl; } } };
#version 140 in vec3 inputPosition; in vec4 inputColor; uniform mat4 projection; uniform mat4 modelview; out vec3 forFragColor; void main(){ forFragColor = inputColor.rgb; gl_Position = projection * modelview * vec4(inputPosition, 1.0); }
#version 140 in vec3 forFragColor; out vec4 outputColor; void main() { outputColor = vec4(forFragColor,1.0); }
class Renderer { private: struct Vertex { float position[3]; float texCoord[2]; float normal[3]; }; public: float t; int modeVal; private: enum {Scene, numVAOs}; enum {SceneAll, numVBOs}; GLuint vaoID[numVAOs]; GLuint bufID[numVBOs]; int sceneVertNo; GLuint progID; GLuint vertID; GLuint fragID; GLint vertexLoc; GLint texCoordLoc; GLint normalLoc; GLint projectionLoc; GLint modelviewLoc; GLint normalMatrixLoc; GLint modeLoc; float projection[16]; // projection matrix float modelview[16]; // modelview matrix public: // constructor Renderer() : t(0.0), modeVal(1), sceneVertNo(0), progID(0), vertID(0), fragID(0), vertexLoc(-1), texCoordLoc(-1), normalLoc(-1), projectionLoc(-1), modelviewLoc(-1), normalMatrixLoc(-1), modeLoc(-1) {} //destructor ~Renderer() { glDeleteVertexArrays(numVAOs, vaoID); glDeleteBuffers(numVBOs, bufID); glDeleteProgram(progID); glDeleteShader(vertID); glDeleteShader(fragID); } public: void init() { initExtensions(); glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH); setupShaders(); // create a Vertex Array Objects (VAO) glGenVertexArrays(numVAOs, vaoID); // generate a Vertex Buffer Object (VBO) glGenBuffers(numVBOs, bufID); // binding the pyramid VAO glBindVertexArray(vaoID[Scene]); std::vector <float> data; int perVertexFloats = (3+2+3); loadVertexData(string("teapot.vbo"), data, perVertexFloats); sceneVertNo = int(data.size()) / perVertexFloats; glBindBuffer(GL_ARRAY_BUFFER, bufID[SceneAll]); glBufferData(GL_ARRAY_BUFFER, sceneVertNo*sizeof(Vertex), &data[0], GL_STATIC_DRAW); int stride = sizeof(Vertex); char *offset = (char*)NULL; // position if(vertexLoc != -1) { glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(vertexLoc); } // texCoord if(texCoordLoc != -1) { offset = (char*)NULL + 3*sizeof(float); glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(texCoordLoc); } // normal if(normalLoc != -1) { offset = (char*)NULL + (3+2)*sizeof(float); glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(normalLoc); } } void setupShaders() { // create shader vertID = glCreateShader(GL_VERTEX_SHADER); fragID = glCreateShader(GL_FRAGMENT_SHADER); // load shader source from file std::string vs = loadShaderSrc("./pass.vert"); const char* vss = vs.c_str(); std::string fs = loadShaderSrc("./pass.frag"); const char* fss = fs.c_str(); // specify shader source glShaderSource(vertID, 1, &(vss), NULL); glShaderSource(fragID, 1, &(fss), NULL); // compile the shader glCompileShader(vertID); glCompileShader(fragID); // check for errors printShaderInfoLog(vertID); printShaderInfoLog(fragID); // create program and attach shaders progID = glCreateProgram(); glAttachShader(progID, vertID); glAttachShader(progID, fragID); // "outColor" is a user-provided OUT variable // of the fragment shader. // Its output is bound to the first color buffer // in the framebuffer glBindFragDataLocation(progID, 0, "outputColor"); // link the program glLinkProgram(progID); // output error messages printProgramInfoLog(progID); // retrieve the location of the IN variables of the vertex shader. vertexLoc = glGetAttribLocation(progID,"inputPosition"); texCoordLoc = glGetAttribLocation(progID,"inputTexCoord"); normalLoc = glGetAttribLocation(progID, "inputNormal"); // retrieve the location of the UNIFORM variables of the vertex shader. projectionLoc = glGetUniformLocation(progID, "projection"); modelviewLoc = glGetUniformLocation(progID, "modelview"); normalMatrixLoc = glGetUniformLocation(progID, "normalMat"); modeLoc = glGetUniformLocation(progID, "mode"); } void resize(int w, int h) { glViewport(0, 0, w, h); // this function replaces gluPerspective mat4Perspective(projection, 30.0f, (float)w/(float)h, 0.5f, 4.0f); // mat4Print(projection); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // camera orbits in the z=2 plane // and looks at the origin // mat4LookAt replaces gluLookAt double rad = M_PI / 180.0f * t; mat4LookAt(modelview, 1.5f*cos(rad), 1.5f*sin(rad), 1.5f, // eye 0.0f, 0.0f, 0.0f, // look at 0.0f, 0.0f, 1.0f); // up float modelviewInv[16], normalmatrix[16]; mat4Invert(modelview, modelviewInv); mat4Transpose(modelviewInv, normalmatrix); glUseProgram(progID); // load the current projection and modelview matrix into the // corresponding UNIFORM variables of the shader glUniformMatrix4fv(projectionLoc, 1, false, projection); glUniformMatrix4fv(modelviewLoc, 1, false, modelview); glUniformMatrix4fv(normalMatrixLoc, 1, false, normalmatrix); glUniform1i(modeLoc, modeVal); // bind Triangle VAO glBindVertexArray(vaoID[Scene]); // render data glDrawArrays(GL_TRIANGLES, 0, sceneVertNo); } private: void printShaderInfoLog(GLuint obj) { int infoLogLength = 0; int returnLength = 0; char *infoLog; glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength); if (infoLogLength > 0) { infoLog = (char *)malloc(infoLogLength); glGetShaderInfoLog(obj, infoLogLength, &returnLength, infoLog); printf("%s\n",infoLog); free(infoLog); } } void printProgramInfoLog(GLuint obj) { int infoLogLength = 0; int returnLength = 0; char *infoLog; glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength); if (infoLogLength > 0) { infoLog = (char *)malloc(infoLogLength); glGetProgramInfoLog(obj, infoLogLength, &returnLength, infoLog); printf("%s\n",infoLog); free(infoLog); } } std::string loadShaderSrc(const std::string& filename) { std::ifstream is(filename); if (is.is_open()) { std::stringstream buffer; buffer << is.rdbuf(); return buffer.str(); } cerr << "Unable to open file " << filename << endl; exit(1); } bool loadVertexData(std::string &filename, std::vector<float> &data, unsigned perVertexFloats) { // read vertex data from file ifstream input(filename.c_str()); if(!input) { QMessageBox msgBox; msgBox.setText("Can not find vertex data file"); msgBox.exec(); return false; } int numFloats; double vertData; if(input >> numFloats) { if(numFloats > 0) { data.resize(numFloats); int i = 0; while(input >> vertData && i < numFloats) { // store it in the vector data[i] = float(vertData); i++; } if(i != numFloats || numFloats % perVertexFloats) return false; } }else{ return false; } return true; } // the following functions are some matrix and vector helpers, // which work for this demo but in general it is recommended // to use more advanced matrix libraries, // e.g. OpenGL Mathematics (GLM) float vec3Dot( float *a, float *b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; } void vec3Cross( float *a, float *b, float *res) { res[0] = a[1] * b[2] - b[1] * a[2]; res[1] = a[2] * b[0] - b[2] * a[0]; res[2] = a[0] * b[1] - b[0] * a[1]; } void vec3Normalize(float *a) { float mag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); a[0] /= mag; a[1] /= mag; a[2] /= mag; } void mat4Identity( float *a) { for (int i = 0; i < 16; ++i) a[i] = 0.0f; for (int i = 0; i < 4; ++i) a[i + i * 4] = 1.0f; } void mat4Multiply(float *a, float *b, float *res) { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { res[j*4 + i] = 0.0f; for (int k = 0; k < 4; ++k) { res[j*4 + i] += a[k*4 + i] * b[j*4 + k]; } } } } void mat4Perspective(float *a, float fov, float aspect, float zNear, float zFar) { float f = 1.0f / float(tan (fov/2.0f * (M_PI / 180.0f))); mat4Identity(a); a[0] = f / aspect; a[1 * 4 + 1] = f; a[2 * 4 + 2] = (zFar + zNear) / (zNear - zFar); a[3 * 4 + 2] = (2.0f * zFar * zNear) / (zNear - zFar); a[2 * 4 + 3] = -1.0f; a[3 * 4 + 3] = 0.0f; } void mat4LookAt(float *viewMatrix, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) { float dir[3], right[3], up[3], eye[3]; up[0]=upX; up[1]=upY; up[2]=upZ; eye[0]=eyeX; eye[1]=eyeY; eye[2]=eyeZ; dir[0]=centerX-eyeX; dir[1]=centerY-eyeY; dir[2]=centerZ-eyeZ; vec3Normalize(dir); vec3Cross(dir,up,right); vec3Normalize(right); vec3Cross(right,dir,up); vec3Normalize(up); // first row viewMatrix[0] = right[0]; viewMatrix[4] = right[1]; viewMatrix[8] = right[2]; viewMatrix[12] = -vec3Dot(right, eye); // second row viewMatrix[1] = up[0]; viewMatrix[5] = up[1]; viewMatrix[9] = up[2]; viewMatrix[13] = -vec3Dot(up, eye); // third row viewMatrix[2] = -dir[0]; viewMatrix[6] = -dir[1]; viewMatrix[10] = -dir[2]; viewMatrix[14] = vec3Dot(dir, eye); // forth row viewMatrix[3] = 0.0f; viewMatrix[7] = 0.0f; viewMatrix[11] = 0.0f; viewMatrix[15] = 1.0f; } void mat4Print(float* a) { // opengl uses column major order for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { cout << a[j * 4 + i] << " "; } cout << endl; } } void mat4Transpose(float* a, float *transposed) { int t = 0; for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { transposed[t++] = a[j * 4 + i]; } } } bool mat4Invert(float* m, float *inverse) { float inv[16]; inv[0] = m[5]*m[10]*m[15]-m[5]*m[11]*m[14]-m[9]*m[6]*m[15]+ m[9]*m[7]*m[14]+m[13]*m[6]*m[11]-m[13]*m[7]*m[10]; inv[4] = -m[4]*m[10]*m[15]+m[4]*m[11]*m[14]+m[8]*m[6]*m[15]- m[8]*m[7]*m[14]-m[12]*m[6]*m[11]+m[12]*m[7]*m[10]; inv[8] = m[4]*m[9]*m[15]-m[4]*m[11]*m[13]-m[8]*m[5]*m[15]+ m[8]*m[7]*m[13]+m[12]*m[5]*m[11]-m[12]*m[7]*m[9]; inv[12]= -m[4]*m[9]*m[14]+m[4]*m[10]*m[13]+m[8]*m[5]*m[14]- m[8]*m[6]*m[13]-m[12]*m[5]*m[10]+m[12]*m[6]*m[9]; inv[1] = -m[1]*m[10]*m[15]+m[1]*m[11]*m[14]+m[9]*m[2]*m[15]- m[9]*m[3]*m[14]-m[13]*m[2]*m[11]+m[13]*m[3]*m[10]; inv[5] = m[0]*m[10]*m[15]-m[0]*m[11]*m[14]-m[8]*m[2]*m[15]+ m[8]*m[3]*m[14]+m[12]*m[2]*m[11]-m[12]*m[3]*m[10]; inv[9] = -m[0]*m[9]*m[15]+m[0]*m[11]*m[13]+m[8]*m[1]*m[15]- m[8]*m[3]*m[13]-m[12]*m[1]*m[11]+m[12]*m[3]*m[9]; inv[13]= m[0]*m[9]*m[14]-m[0]*m[10]*m[13]-m[8]*m[1]*m[14]+ m[8]*m[2]*m[13]+m[12]*m[1]*m[10]-m[12]*m[2]*m[9]; inv[2] = m[1]*m[6]*m[15]-m[1]*m[7]*m[14]-m[5]*m[2]*m[15]+ m[5]*m[3]*m[14]+m[13]*m[2]*m[7]-m[13]*m[3]*m[6]; inv[6] = -m[0]*m[6]*m[15]+m[0]*m[7]*m[14]+m[4]*m[2]*m[15]- m[4]*m[3]*m[14]-m[12]*m[2]*m[7]+m[12]*m[3]*m[6]; inv[10]= m[0]*m[5]*m[15]-m[0]*m[7]*m[13]-m[4]*m[1]*m[15]+ m[4]*m[3]*m[13]+m[12]*m[1]*m[7]-m[12]*m[3]*m[5]; inv[14]= -m[0]*m[5]*m[14]+m[0]*m[6]*m[13]+m[4]*m[1]*m[14]- m[4]*m[2]*m[13]-m[12]*m[1]*m[6]+m[12]*m[2]*m[5]; inv[3] = -m[1]*m[6]*m[11]+m[1]*m[7]*m[10]+m[5]*m[2]*m[11]- m[5]*m[3]*m[10]-m[9]*m[2]*m[7]+m[9]*m[3]*m[6]; inv[7] = m[0]*m[6]*m[11]-m[0]*m[7]*m[10]-m[4]*m[2]*m[11]+ m[4]*m[3]*m[10]+m[8]*m[2]*m[7]-m[8]*m[3]*m[6]; inv[11]= -m[0]*m[5]*m[11]+m[0]*m[7]*m[9]+m[4]*m[1]*m[11]- m[4]*m[3]*m[9]-m[8]*m[1]*m[7]+m[8]*m[3]*m[5]; inv[15]= m[0]*m[5]*m[10]-m[0]*m[6]*m[9]-m[4]*m[1]*m[10]+ m[4]*m[2]*m[9]+m[8]*m[1]*m[6]-m[8]*m[2]*m[5]; float det = m[0]*inv[0]+m[1]*inv[4]+m[2]*inv[8]+m[3]*inv[12]; if (det == 0) return false; det = 1.0f / det; for (int i = 0; i < 16; i++) inverse[i] = inv[i] * det; return true; } };
#version 140 in vec3 inputPosition; in vec2 inputTexCoord; in vec3 inputNormal; uniform mat4 projection, modelview, normalMat; uniform int mode; out vec4 forFragColor; void main(){ gl_Position = projection * modelview * vec4(inputPosition, 1.0); vec4 normal = normalMat * vec4(inputNormal, 0.0); if(mode == 1) forFragColor = normal; if(mode == 2) forFragColor = vec4(inputNormal, 1.0); if(mode == 3) forFragColor = gl_Position; if(mode == 4) forFragColor = vec4(inputPosition, 1.0); if(mode == 5) forFragColor = vec4(inputTexCoord, 0.0, 1.0); }
#version 140 in vec4 forFragColor; out vec4 outputColor; void main() { outputColor = forFragColor; }
uniform
-Variable vom Typ sampler
definiert werden, z.B. bei einer 2D Textur: uniform sampler2D myTexture;
texture(...)
erfolgt dann der Zugriff auf eine Texturkoordinate $(s,t)$: texture(myTexture, vec2(s,t))
glGenTexture
und glBindTexture
erzeugt,
Parameter mit glTexParameter
gesetzt und die Texturdaten mittels glTexImage
übergeben
sampler
-Variable ermittelt werden texLoc = glGetUniformLocation(progID, "myTexture");
sampler
-Variable
übergeben: glActiveTexture(GL_TEXTURE0); // activate texture unit 0 glBindTexture(GL_TEXTURE_2D, texID); // bind texture glUniform1i(texLoc, 0); // inform the shader to use texture unit 0
class Renderer { private: struct Vertex { float position[3]; float color[4]; float texCoord[2]; float normal[3]; }; public: float t; private: enum {Pyramid, numVAOs}; enum {PyramidAll, numVBOs}; GLuint vaoID[numVAOs]; GLuint bufID[numVBOs]; int pyramidVertNo; GLuint texID; GLuint progID; GLuint vertID; GLuint fragID; GLint vertexLoc; GLint colorLoc; GLint texCoordLoc; GLint normalLoc; GLint projectionLoc; GLint modelviewLoc; GLint texLoc; float projection[16]; // projection matrix float modelview[16]; // modelview matrix public: // constructor Renderer() : t(0.0), pyramidVertNo(0), texID(0), progID(0), vertID(0), fragID(0), vertexLoc(-1), colorLoc(-1), texCoordLoc(-1), normalLoc(-1), projectionLoc(-1), modelviewLoc(-1), texLoc(-1) {} //destructor ~Renderer() { glDeleteVertexArrays(numVAOs, vaoID); glDeleteBuffers(numVBOs, bufID); glDeleteProgram(progID); glDeleteShader(vertID); glDeleteShader(fragID); } public: void init() { initExtensions(); glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH); setupShaders(); // create a Vertex Array Objects (VAO) glGenVertexArrays(numVAOs, vaoID); // generate a Vertex Buffer Object (VBO) glGenBuffers(numVBOs, bufID); // bind the pyramid VAO glBindVertexArray(vaoID[Pyramid]); float pyramidVertexData[] = { 0.0f, 0.0f, 2.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.5f, 1.0f, 0.0000f,-0.9701f, 0.2425f, -0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0000f,-0.9701f, 0.2425f, 0.5f,-0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0000f,-0.9701f, 0.2425f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.5f, 1.0f, 0.9701f, 0.0000f, 0.2425f, 0.5f,-0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.9701f, 0.0000f, 0.2425f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.9701f, 0.0000f, 0.2425f, 0.0f, 0.0f, 2.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f, 1.0f, 0.0000f, 0.9701f, 0.2425f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0000f, 0.9701f, 0.2425f, -0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0000f, 0.9701f, 0.2425f, 0.0f, 0.0f, 2.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.5f, 1.0f,-0.9701f, 0.0000f, 0.2425f, -0.5f, 0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,-0.9701f, 0.0000f, 0.2425f, -0.5f,-0.5f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,-0.9701f, 0.0000f, 0.2425f }; pyramidVertNo = 12; glBindBuffer(GL_ARRAY_BUFFER, bufID[PyramidAll]); glBufferData(GL_ARRAY_BUFFER, pyramidVertNo*sizeof(Vertex), pyramidVertexData, GL_STATIC_DRAW); int stride = sizeof(Vertex); char *offset = (char*)NULL; // position if(vertexLoc != -1) { glVertexAttribPointer(vertexLoc, 3, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(vertexLoc); } // color if(colorLoc != -1) { offset = (char*)NULL + 3*sizeof(float); glVertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(colorLoc); } // texCoord if(texCoordLoc != -1) { offset = (char*)NULL + (3+4)*sizeof(float); glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(texCoordLoc); } // normal if(normalLoc != -1) { offset = (char*)NULL + (3+4+2)*sizeof(float); glVertexAttribPointer(normalLoc, 3, GL_FLOAT, GL_FALSE, stride, offset); glEnableVertexAttribArray(normalLoc); } std::string fileName("./checkerboard.ppm"); texID = loadTexture(fileName); } void setupShaders() { // create shader vertID = glCreateShader(GL_VERTEX_SHADER); fragID = glCreateShader(GL_FRAGMENT_SHADER); // load shader source from file std::string vs = loadShaderSrc("./texture.vert"); const char* vss = vs.c_str(); std::string fs = loadShaderSrc("./texture.frag"); const char* fss = fs.c_str(); // specify shader source glShaderSource(vertID, 1, &(vss), NULL); glShaderSource(fragID, 1, &(fss), NULL); // compile the shader glCompileShader(vertID); glCompileShader(fragID); // check for errors printShaderInfoLog(vertID); printShaderInfoLog(fragID); // create program and attach shaders progID = glCreateProgram(); glAttachShader(progID, vertID); glAttachShader(progID, fragID); // "outColor" is a user-provided OUT variable // of the fragment shader. // Its output is bound to the first color buffer // in the framebuffer glBindFragDataLocation(progID, 0, "outputColor"); // link the program glLinkProgram(progID); // output error messages printProgramInfoLog(progID); // retrieve the location of the IN variables of the vertex shader. vertexLoc = glGetAttribLocation(progID,"inputPosition"); colorLoc = glGetAttribLocation(progID, "inputColor"); texCoordLoc = glGetAttribLocation(progID,"inputTexCoord"); normalLoc = glGetAttribLocation(progID, "inputNormal"); // retrieve the location of the UNIFORM variables of the vertex shader. projectionLoc = glGetUniformLocation(progID, "projection"); modelviewLoc = glGetUniformLocation(progID, "modelview"); texLoc = glGetUniformLocation(progID, "myTexture"); } void resize(int w, int h) { glViewport(0, 0, w, h); // this function replaces gluPerspective mat4Perspective(projection, 30.0f, (float)w/(float)h, 1.0f, 10.0f); // mat4Print(projection); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // camera orbits in the z=5 plane // and looks at the origin // mat4LookAt replaces gluLookAt double rad = M_PI / 180.0f * t; mat4LookAt(modelview, 5.0f*cos(rad), 5.0f*sin(rad), 5.0f, // eye 0.0f, 0.0f, 0.5f, // look at 0.0f, 0.0f, 1.0f); // up glUseProgram(progID); // load the current projection and modelview matrix into the // corresponding UNIFORM variables of the shader glUniformMatrix4fv(projectionLoc, 1, false, projection); glUniformMatrix4fv(modelviewLoc, 1, false, modelview); // activate texture unit 0 glActiveTexture(GL_TEXTURE0); // bind texture glBindTexture(GL_TEXTURE_2D, texID); // inform the shader to use texture unit 0 glUniform1i(texLoc, 0); // bind pyramid VAO glBindVertexArray(vaoID[Pyramid]); // render data glDrawArrays(GL_TRIANGLES, 0, pyramidVertNo); } private: void printShaderInfoLog(GLuint obj) { int infoLogLength = 0; int returnLength = 0; char *infoLog; glGetShaderiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength); if (infoLogLength > 0) { infoLog = (char *)malloc(infoLogLength); glGetShaderInfoLog(obj, infoLogLength, &returnLength, infoLog); printf("%s\n",infoLog); free(infoLog); } } void printProgramInfoLog(GLuint obj) { int infoLogLength = 0; int returnLength = 0; char *infoLog; glGetProgramiv(obj, GL_INFO_LOG_LENGTH,&infoLogLength); if (infoLogLength > 0) { infoLog = (char *)malloc(infoLogLength); glGetProgramInfoLog(obj, infoLogLength, &returnLength, infoLog); printf("%s\n",infoLog); free(infoLog); } } std::string loadShaderSrc(const std::string& filename) { std::ifstream is(filename); if (is.is_open()) { std::stringstream buffer; buffer << is.rdbuf(); return buffer.str(); } cerr << "Unable to open file " << filename << endl; exit(1); } // the following functions are some matrix and vector helpers // they work for this demo but in general it is recommended // to use more advanced matrix libraries, // e.g. OpenGL Mathematics (GLM) float vec3Dot( float *a, float *b) { return a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; } void vec3Cross( float *a, float *b, float *res) { res[0] = a[1] * b[2] - b[1] * a[2]; res[1] = a[2] * b[0] - b[2] * a[0]; res[2] = a[0] * b[1] - b[0] * a[1]; } void vec3Normalize(float *a) { float mag = sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]); a[0] /= mag; a[1] /= mag; a[2] /= mag; } void mat4Identity( float *a) { for (int i = 0; i < 16; ++i) a[i] = 0.0f; for (int i = 0; i < 4; ++i) a[i + i * 4] = 1.0f; } void mat4Multiply(float *a, float *b, float *res) { for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { res[j*4 + i] = 0.0f; for (int k = 0; k < 4; ++k) { res[j*4 + i] += a[k*4 + i] * b[j*4 + k]; } } } } void mat4Perspective(float *a, float fov, float aspect, float zNear, float zFar) { float f = 1.0f / float(tan (fov/2.0f * (M_PI / 180.0f))); mat4Identity(a); a[0] = f / aspect; a[1 * 4 + 1] = f; a[2 * 4 + 2] = (zFar + zNear) / (zNear - zFar); a[3 * 4 + 2] = (2.0f * zFar * zNear) / (zNear - zFar); a[2 * 4 + 3] = -1.0f; a[3 * 4 + 3] = 0.0f; } void mat4LookAt(float *viewMatrix, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ) { float dir[3], right[3], up[3], eye[3]; up[0]=upX; up[1]=upY; up[2]=upZ; eye[0]=eyeX; eye[1]=eyeY; eye[2]=eyeZ; dir[0]=centerX-eyeX; dir[1]=centerY-eyeY; dir[2]=centerZ-eyeZ; vec3Normalize(dir); vec3Cross(dir,up,right); vec3Normalize(right); vec3Cross(right,dir,up); vec3Normalize(up); // first row viewMatrix[0] = right[0]; viewMatrix[4] = right[1]; viewMatrix[8] = right[2]; viewMatrix[12] = -vec3Dot(right, eye); // second row viewMatrix[1] = up[0]; viewMatrix[5] = up[1]; viewMatrix[9] = up[2]; viewMatrix[13] = -vec3Dot(up, eye); // third row viewMatrix[2] = -dir[0]; viewMatrix[6] = -dir[1]; viewMatrix[10] = -dir[2]; viewMatrix[14] = vec3Dot(dir, eye); // forth row viewMatrix[3] = 0.0; viewMatrix[7] = 0.0; viewMatrix[11] = 0.0; viewMatrix[15] = 1.0f; } void mat4Print(float* a) { // opengl uses column major order for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { cout << a[j * 4 + i] << " "; } cout << endl; } } // returns a valid textureID on success, otherwise 0 GLuint loadTexture(std::string &filename) { unsigned width; unsigned height; int level = 0; int border = 0; std::vector<unsigned char> imgData; // load image data if(!loadPPMImageFlipped(filename, width, height, imgData)) return 0; // data is aligned in byte order glPixelStorei(GL_UNPACK_ALIGNMENT, 1); //request textureID GLuint textureID; glGenTextures( 1, &textureID); // bind texture glBindTexture( GL_TEXTURE_2D, textureID); //define how to filter the texture (important but ignore for now) glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //texture colors should replace the original color values glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //GL_MODULATE // specify the 2D texture map glTexImage2D(GL_TEXTURE_2D, level, GL_RGB, width, height, border, GL_RGB, GL_UNSIGNED_BYTE, &imgData[0]); // return unique texture identifier return textureID; } bool loadPPMImageFlipped(std::string &filename, unsigned &width, unsigned &height, std::vector<unsigned char> &imgData) { ifstream input(filename.c_str(), ifstream::in | ifstream::binary); if(!input) { // cast istream to bool to see if something went wrong QMessageBox msgBox; msgBox.setText(QString("Can not find texture data file ") + QString(filename.c_str())); msgBox.exec(); return false; } input.unsetf(std::ios_base::skipws); string line; input >> line >> std::ws; if (line != "P6") { QMessageBox msgBox; msgBox.setText("File is not PPM P6 raw format"); msgBox.exec(); return false; } width = 0; height = 0; unsigned depth = 0; unsigned readItems = 0; unsigned char lastCharBeforeBinary; while (readItems < 3) { input >> std::ws; if(input.peek() != '#') { if (readItems == 0) input >> width; if (readItems == 1) input >> height; if (readItems == 2) input >> depth >> lastCharBeforeBinary; readItems++; }else{ // skip comments std::getline(input, line); } } if(depth >= 256) { QMessageBox msgBox; msgBox.setText("Only 8-bit PPM format is supported"); msgBox.exec(); return false; } unsigned byteCount = width * height * 3; imgData.resize(byteCount); input.read((char*)&imgData[0], byteCount*sizeof(unsigned char)); // vertically flip the image because the image origin // in OpenGL is the lower-left corner unsigned char tmpData; for(unsigned y=0; y < height / 2; y++) { int sourceIndex = y * width * 3; int targetIndex = (height-1-y) * width *3; for(unsigned x=0; x < width*3; x++) { tmpData = imgData[targetIndex]; imgData[targetIndex] = imgData[sourceIndex]; imgData[sourceIndex] = tmpData; sourceIndex++; targetIndex++; } } return true; } };
#version 140 in vec3 inputPosition; in vec4 inputColor; in vec2 inputTexCoord; in vec3 inputNormal; uniform mat4 projection, modelview; out vec3 forFragColor; out vec2 forFragTexCoord; void main(){ forFragColor = inputColor.rgb; forFragTexCoord = inputTexCoord; gl_Position = projection * modelview * vec4(inputPosition, 1.0); }
#version 140 in vec3 forFragColor; in vec2 forFragTexCoord; out vec4 outputColor; uniform sampler2D myTexture; void main() { vec3 textureColor = vec3( texture(myTexture, forFragTexCoord) ); outputColor = vec4(forFragColor*textureColor,1.0); }
#version 140 in vec3 forFragColor; in vec2 forFragTexCoord; out vec4 outputColor; uniform sampler2D myTexture; void main() { vec3 textureColor = vec3( texture(myTexture, forFragTexCoord) ); outputColor = vec4(forFragColor*textureColor,1.0); if(forFragTexCoord.x > 0.5) outputColor = vec4(1.0, 0.0, 0.0, 1.0); }
#version 140 in vec3 forFragColor; in vec2 forFragTexCoord; out vec4 outputColor; uniform sampler2D myTexture; const vec2 texSize = vec2(256.0,256.0); void main() { vec3 tC = vec3( texture(myTexture, forFragTexCoord) ); vec3 tC2 = vec3( texture(myTexture, forFragTexCoord + vec2(1.0/texSize.x, 0.0) ) ); vec3 tC3 = vec3( texture(myTexture, forFragTexCoord + vec2(0.0, 1.0/texSize.y) ) ); if(abs(tC.x - tC2.x) > 0.01) { outputColor = vec4(1.0,1.0,1.0,1.0); }else { if(abs(tC.x - tC3.x) > 0.01) { outputColor = vec4(1.0,1.0,0.0,1.0); }else { outputColor = vec4(forFragColor*tC,1.0); } } }
gl_FragDepth
verändert, kann der Depth-Test nicht vorgezogen werden#version 420 layout(early_fragment_tests) in;
Anregungen oder Verbesserungsvorschläge können auch gerne per E-mail an mich gesendet werden: Kontakt