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);
}