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, mat4int, ivec2, ivec3, ivec4, uint, uvec2, uvec3, uvec4bool, bvec2, bvec3, bvec4sampler2D, sampler3D, samplerCube, ...
struct Vertex {
float val1;
int val2;
bool val3;
};float a[16];
float a = float(1);
if, if()elsefor, while, do{}while()return, break, continuebyte, short, long-Typen, Kein unionswitch()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