Let's fetch this week's upstream changes.
$ cd ~/cs40/examples $ git fetch upstream $ git merge -X ours upstream/master
After this step, you will need to manually edit the top level CMakeLists.txt
to add the new subdirectories.
$ tail ~/cs40/examples/CMakeLists.txt if(CMAKE_CUDA_COMPILER) add_subdirectory(w07-cuda-pt1) add_subdirectory(w07-cuda-pt2) add_subdirectory(w08-cuda-patterns) endif() add_subdirectory(w09-particles) add_subdirectory(w10-noise) add_subdirectory(w11-noise2) #add the line below add_subdirectory(w12-gshader)
No symlink this week.
If everything went well, you should be able to go into your build
directory and run make -j8
to compile the week 10 examples.
cd build make -j8 cd w12-gshader ./gshader
X,Y,Z
will rotate the scene. P
toggles polygon mode, C
toggles culling. N
toggles drawing normals.
First let's modify the main
in the geometry shader to be a bit more modular.
void drawNormals() { makeNormalLine(0); makeNormalLine(1); makeNormalLine(2); } void main() { drawNormals(); //drawExplode(); }
Next, add two helper functions for computing the planar normal and moving a vertex index along a given normal by a specified length.
vec3 triNormal() { vec3 a = vec3(gl_in[1].gl_Position) - vec3(gl_in[0].gl_Position); vec3 b = vec3(gl_in[2].gl_Position) - vec3(gl_in[1].gl_Position); return normalize(cross(a, b)); } vec4 explode(int index, vec3 normal, float magnitude) { mat4 mvp = projection * camera * model; vec3 direction = normal * ((cos(time) + 1.0) / 2.0) * magnitude; return mvp * (gl_in[index].gl_Position + vec4(direction, 0.0)); }
This example uses a new uniform time
that we can later modify to animate the explosion effect. Add the uniform to the list of uniforms at the top of your shader.
uniform float time=0;
Complete the implementation of drawExplode
below and uncomment the drawExplode
call in main when you are ready to test.
void drawExplode() { vec3 norm = triNormal(); float magnitude = 0.3; color = vec4(1, 1, 1, 1); //TODO: complete implementation //TODO: you will need to change the output type of the shader at //the top of your program. What is it now? What should it be? }
If you want to animate, one easy way to do this is to add two member variables to your MyPanelOpenGL
class.
QTimer m_timer; QTime m_time;and a new slot
public slots: void step();
Connect the Timer
to the step slot in initializeGL
in your mypanelopengl.cpp
file. The step slot can just call update as shown below.
void MyPanelOpenGL::initializeGL() { ... connect(&m_timer, &QTimer::timeout, this, &MyPanelOpenGL::step); m_timer.start(30); /*fire every 30ms */ } void MyPanelOpenGL::step() { update(); }
The m_time
variable, not m_timer
will set the value for the time uniform in our shader. Initialize m_time
in the constructor.
m_time.start();You can fetch the result in
MyPanelOpenGL::setUniforms
.
if(m_drawNormals){ float t = 3. * m_time.elapsed() / 1000.; m_shaderPrograms[prog]->setUniformValue("time", t); }