1 \documentclass{article}
8 \title{CS4052 Assignment 1}
11 \lstset{basicstyle=\ttfamily}
13 \section{Fragment shader colours}
14 In order to get the fragment shader to use the position as the colour,
15 I had to add an input \texttt{vec4} for the \texttt{vec4 color} that the vertex shader
16 outputted. Since the inputs to the fragment shader are from the vertex shader, I had to
17 use \texttt{color} and not \texttt{vColor}.
18 \lstinputlisting[language=C++]{fragment.glsl}
20 \includegraphics[width=0.8\textwidth]{part1}
24 \section{Two triangles}
26 Two add two triangles, I had to increase the number of vertices drawn to 6
28 \begin{lstlisting}[language=C++]
29 glDrawArrays(GL_TRIANGLES, 0, 6);
32 And add 9 new coordinates and colours for them.
34 \begin{lstlisting}[language=C++]
35 GLfloat vertices[] = {
54 \includegraphics[width=0.8\textwidth]{part2}
58 \section{Two triangles, two VAOs and two VBOs}
60 In order to use two VAOs and two VBOs, I had to combine the VAO setup and the VBO setup
61 into one function, since you need to bind the VBO at the time that you create the
64 \begin{lstlisting}[language=C++]
65 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
67 GLuint setupBuffers(GLfloat* vertices, GLuint progId) {
78 glGenBuffers(1, &vbo);
81 glGenVertexArrays(1, &vao);
83 GLuint posId = glGetAttribLocation(progId, "vPosition");
84 GLuint colorId = glGetAttribLocation(progId, "vColor");
86 GLuint vertsLen = numVerts * 3 * sizeof(GLfloat);
87 GLuint colorsLen = numVerts * 4 * sizeof(GLfloat);
89 glBindBuffer(GL_ARRAY_BUFFER, vbo);
90 glBufferData(GL_ARRAY_BUFFER, vertsLen + colorsLen, NULL, GL_STATIC_DRAW);
92 glBufferSubData(GL_ARRAY_BUFFER, 0, vertsLen, vertices);
93 glBufferSubData(GL_ARRAY_BUFFER, vertsLen, colorsLen, colors);
95 glBindVertexArray(vao);
97 glEnableVertexAttribArray(posId);
98 glEnableVertexAttribArray(colorId);
100 glVertexAttribPointer(posId, 3, GL_FLOAT, GL_FALSE, 0, 0);
101 glVertexAttribPointer(colorId, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(numVerts * 3 * sizeof(GLfloat)));
107 This could then be used like so:
108 \begin{lstlisting}[language=C++]
109 GLfloat vertices[2][9] = {
122 GLuint* vaos = new GLuint[2];
123 vaos[0] = setupBuffers(vertices[0], progId);
124 vaos[1] = setupBuffers(vertices[1], progId);
127 When drawing, the VAOs needed to be switched out:
129 \begin{lstlisting}[language=C++]
131 glClear(GL_COLOR_BUFFER_BIT);
132 for (int i = 0; i < 2; i++) {
133 glBindVertexArray(vaos[i]);
134 glDrawArrays(GL_TRIANGLES, 0, 3);
140 \section{Two separate shaders}
142 I modified the \texttt{compileShaders} function to load in the shader source from a file:
143 \begin{lstlisting}[language=C++]
144 GLuint compileShaders(char* vertexShader, char* fragmentShader) {
145 GLuint progId = glCreateProgram();
147 attachShader(progId, vertexShader, GL_VERTEX_SHADER);
148 attachShader(progId, fragmentShader, GL_FRAGMENT_SHADER);
150 glLinkProgram(progId);
152 glGetProgramiv(progId, GL_LINK_STATUS, &success);
155 glGetProgramInfoLog(progId, sizeof(log), NULL, log);
156 fprintf(stderr, "error linking: %s\n", log);
164 Which meant I could easily swap out the programs used when setting up the buffers:
166 \begin{lstlisting}[language=C++]
167 progIds = new GLuint[2];
169 GLuint progId1 = compileShaders((char*)"vertex.glsl", (char*)"fragment.glsl");
170 vaos[0] = setupBuffers(vertices[0], progId1);
171 progIds[0] = progId1;
172 validateProgram(progId1);
174 GLuint progId2 = compileShaders((char*)"vertex.glsl", (char*)"yellow.glsl");
175 vaos[1] = setupBuffers(vertices[1], progId2);
176 progIds[1] = progId2;
177 validateProgram(progId2);
180 The new yellow shader looked like this:
182 \lstinputlisting[language=C++]{yellow.glsl}
184 I needed to switch programs during the display function:
186 \begin{lstlisting}[language=C++]
188 glClear(GL_COLOR_BUFFER_BIT);
189 for (int i = 0; i < 2; i++) {
190 glUseProgram(progIds[i]);
191 glBindVertexArray(vaos[i]);
192 glDrawArrays(GL_TRIANGLES, 0, 3);
199 \includegraphics[width=0.8\textwidth]{part4}