diff --git a/Project Readme.md b/Project Readme.md new file mode 100644 index 0000000..5c8f811 --- /dev/null +++ b/Project Readme.md @@ -0,0 +1,25 @@ +IMAGE PROCESSING AND WEBGL + + +PART 1: + +- Implemented all necessary image processing filters. +- In the 3 extra filters, I have made custom filters: + - The first filter keeps only the portions of image that have high luminance and does not show the rest of the image. This gives a kind of comic book effect with black and white images. + - The other 2 filters just output a component of the colors (red and magenta). This is nothing special so I don't think I will get any points for these. + + +PART 2: + +- Implemented the sine wave and simplex vertex shaders. +- My custom implementation has a sine of exponent which gives a nice cloth-in-the-wind like effect. + + +SCREENSHOTS: + +- See blog + + +BLOG POST: + +experiencetheforce.blogspot.com \ No newline at end of file diff --git a/part1/ImageProcessing/ImageProcessing.sdf b/part1/ImageProcessing/ImageProcessing.sdf new file mode 100644 index 0000000..f105b21 Binary files /dev/null and b/part1/ImageProcessing/ImageProcessing.sdf differ diff --git a/part1/ImageProcessing/ImageProcessing.sln b/part1/ImageProcessing/ImageProcessing.sln index f84e097..a563da7 100644 --- a/part1/ImageProcessing/ImageProcessing.sln +++ b/part1/ImageProcessing/ImageProcessing.sln @@ -1,29 +1,31 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageProcessing", "ImageProcessing\ImageProcessing.vcxproj", "{C53A9886-B4FD-487A-83A5-01406BA9E8BF}" - ProjectSection(ProjectDependencies) = postProject - {25544C77-3B78-405F-A15D-1231D05969F3} = {25544C77-3B78-405F-A15D-1231D05969F3} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SOIL", "SOIL\SOIL.vcxproj", "{25544C77-3B78-405F-A15D-1231D05969F3}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {25544C77-3B78-405F-A15D-1231D05969F3}.Debug|Win32.ActiveCfg = Debug|Win32 - {25544C77-3B78-405F-A15D-1231D05969F3}.Debug|Win32.Build.0 = Debug|Win32 - {25544C77-3B78-405F-A15D-1231D05969F3}.Release|Win32.ActiveCfg = Release|Win32 - {25544C77-3B78-405F-A15D-1231D05969F3}.Release|Win32.Build.0 = Release|Win32 - {C53A9886-B4FD-487A-83A5-01406BA9E8BF}.Debug|Win32.ActiveCfg = Debug|Win32 - {C53A9886-B4FD-487A-83A5-01406BA9E8BF}.Debug|Win32.Build.0 = Debug|Win32 - {C53A9886-B4FD-487A-83A5-01406BA9E8BF}.Release|Win32.ActiveCfg = Release|Win32 - {C53A9886-B4FD-487A-83A5-01406BA9E8BF}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ImageProcessing", "ImageProcessing\ImageProcessing.vcxproj", "{C53A9886-B4FD-487A-83A5-01406BA9E8BF}" + ProjectSection(ProjectDependencies) = postProject + {25544C77-3B78-405F-A15D-1231D05969F3} = {25544C77-3B78-405F-A15D-1231D05969F3} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SOIL", "SOIL\SOIL.vcxproj", "{25544C77-3B78-405F-A15D-1231D05969F3}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{897A09B4-CB4F-429A-B46E-8A85628EF166}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C53A9886-B4FD-487A-83A5-01406BA9E8BF}.Debug|Win32.ActiveCfg = Debug|Win32 + {C53A9886-B4FD-487A-83A5-01406BA9E8BF}.Debug|Win32.Build.0 = Debug|Win32 + {C53A9886-B4FD-487A-83A5-01406BA9E8BF}.Release|Win32.ActiveCfg = Release|Win32 + {C53A9886-B4FD-487A-83A5-01406BA9E8BF}.Release|Win32.Build.0 = Release|Win32 + {25544C77-3B78-405F-A15D-1231D05969F3}.Debug|Win32.ActiveCfg = Debug|Win32 + {25544C77-3B78-405F-A15D-1231D05969F3}.Debug|Win32.Build.0 = Debug|Win32 + {25544C77-3B78-405F-A15D-1231D05969F3}.Release|Win32.ActiveCfg = Release|Win32 + {25544C77-3B78-405F-A15D-1231D05969F3}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/part1/ImageProcessing/ImageProcessing/ImageProcessing.vcxproj b/part1/ImageProcessing/ImageProcessing/ImageProcessing.vcxproj index 554291c..33c6ff9 100644 --- a/part1/ImageProcessing/ImageProcessing/ImageProcessing.vcxproj +++ b/part1/ImageProcessing/ImageProcessing/ImageProcessing.vcxproj @@ -1,110 +1,118 @@ - - - - - Debug - Win32 - - - Release - Win32 - - - - - - - - - - - - - - - - ImageProcessing - {C53A9886-B4FD-487A-83A5-01406BA9E8BF} - Box_Blur - Win32Proj - - - - Application - Unicode - true - - - Application - Unicode - - - - - - - - - - - - - <_ProjectFileVersion>10.0.30319.1 - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - true - $(SolutionDir)$(Configuration)\ - $(Configuration)\ - false - - - - Disabled - ..\..\shared32\glew\include;..\..\shared32\freeglut\include;..\Shader_Loading;..\SOIL;%(AdditionalIncludeDirectories) - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) - true - EnableFastChecks - MultiThreadedDebugDLL - - - Level3 - EditAndContinue - - - glew32.lib;%(AdditionalDependencies) - ..\..\shared32\glew\lib;..\..\shared32\freeglut\lib;%(AdditionalLibraryDirectories) - true - Console - MachineX86 - - - - - MaxSpeed - true - WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) - MultiThreadedDLL - true - - - Level3 - ProgramDatabase - - - true - Console - true - true - MachineX86 - - - - - {25544c77-3b78-405f-a15d-1231d05969f3} - false - - - - - + + + + + Debug + Win32 + + + Release + Win32 + + + + + + + + + + + + + + + + + + + + + + + + ImageProcessing + {C53A9886-B4FD-487A-83A5-01406BA9E8BF} + Box_Blur + Win32Proj + + + + Application + Unicode + true + + + Application + Unicode + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + true + $(SolutionDir)$(Configuration)\ + $(Configuration)\ + false + + + + Disabled + ..\..\shared32\glew\include;..\..\shared32\freeglut\include;..\Shader_Loading;..\SOIL;%(AdditionalIncludeDirectories) + WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + EditAndContinue + + + glew32.lib;%(AdditionalDependencies) + ..\..\shared32\glew\lib;..\..\shared32\freeglut\lib;%(AdditionalLibraryDirectories) + true + Console + MachineX86 + + + + + MaxSpeed + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + MultiThreadedDLL + true + + + Level3 + ProgramDatabase + + + true + Console + true + true + MachineX86 + + + + + {25544c77-3b78-405f-a15d-1231d05969f3} + false + + + + + \ No newline at end of file diff --git a/part1/ImageProcessing/ImageProcessing/ImageProcessing.vcxproj.user b/part1/ImageProcessing/ImageProcessing/ImageProcessing.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/part1/ImageProcessing/ImageProcessing/ImageProcessing.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/part1/ImageProcessing/ImageProcessing/Thumbs.db b/part1/ImageProcessing/ImageProcessing/Thumbs.db new file mode 100644 index 0000000..031ec0b Binary files /dev/null and b/part1/ImageProcessing/ImageProcessing/Thumbs.db differ diff --git a/part1/ImageProcessing/ImageProcessing/blackFS.glsl b/part1/ImageProcessing/ImageProcessing/blackFS.glsl new file mode 100644 index 0000000..3463954 --- /dev/null +++ b/part1/ImageProcessing/ImageProcessing/blackFS.glsl @@ -0,0 +1,17 @@ +varying vec2 v_Texcoords; + +uniform sampler2D u_image; + +void main(void) +{ + vec3 temp = texture2D(u_image, v_Texcoords).rgb; + const vec3 W = vec3(0.2125, 0.7154, 0.0721); + float luminance = dot(temp.rgb, W); + + if(luminance > 0.9) + luminance = 1.0; + else + luminance = 0.0; + + gl_FragColor = vec4(vec3(luminance * temp.rgb), 1.0); +} diff --git a/part1/ImageProcessing/ImageProcessing/edgeDetectionFS.glsl b/part1/ImageProcessing/ImageProcessing/edgeDetectionFS.glsl new file mode 100644 index 0000000..bc91904 --- /dev/null +++ b/part1/ImageProcessing/ImageProcessing/edgeDetectionFS.glsl @@ -0,0 +1,31 @@ +varying vec2 v_Texcoords; + +uniform sampler2D u_image; +uniform vec2 u_step; + +const int KERNEL_WIDTH = 3; // Odd +const float offset = 1.0; + +void main(void) +{ + //vec3 accum = vec3(0.0); + const vec3 W = vec3(0.2125, 0.7154, 0.0721); + mat3 sobelH = mat3(vec3(-1,-2,-1),vec3(0,0,0),vec3(1,2,1)); + mat3 sobelV = mat3(vec3(-1,0,1),vec3(-2,0,2),vec3(-1,0,1)); + float luminanceH = 0.0; + float luminanceV = 0.0; + + for (int i = 0; i < KERNEL_WIDTH; ++i) + { + for (int j = 0; j < KERNEL_WIDTH; ++j) + { + vec2 coord = vec2(v_Texcoords.s + ((float(i) - offset) * u_step.s), v_Texcoords.t + ((float(j) - offset) * u_step.t)); + luminanceH += sobelH[i][j] * dot(texture2D(u_image, coord).rgb, W); + luminanceV += sobelV[i][j] * dot(texture2D(u_image, coord).rgb, W); + } + } + + vec2 edge = vec2(luminanceH, luminanceV); + float edgeIntensity = length(edge); + gl_FragColor = vec4(vec3(edgeIntensity), 1.0); +} diff --git a/part1/ImageProcessing/ImageProcessing/gaussianBlurFS.glsl b/part1/ImageProcessing/ImageProcessing/gaussianBlurFS.glsl new file mode 100644 index 0000000..5afd93b --- /dev/null +++ b/part1/ImageProcessing/ImageProcessing/gaussianBlurFS.glsl @@ -0,0 +1,24 @@ +varying vec2 v_Texcoords; + +uniform sampler2D u_image; +uniform vec2 u_step; + +const int KERNEL_WIDTH = 3; // Odd +const float offset = 1.0; + +void main(void) +{ + vec3 accum = vec3(0.0); + mat3 mask = mat3(vec3(1,2,1),vec3(2,4,2),vec3(1,2,1))/16.0; + + for (int i = 0; i < KERNEL_WIDTH; ++i) + { + for (int j = 0; j < KERNEL_WIDTH; ++j) + { + vec2 coord = vec2(v_Texcoords.s + /*mask[i][j] * */((float(i) - offset) * u_step.s), v_Texcoords.t + /*mask[i][j] * */((float(j) - offset) * u_step.t)); + accum += mask[i][j] * texture2D(u_image, coord).rgb; + } + } + + gl_FragColor = vec4(accum/* / float(KERNEL_WIDTH * KERNEL_WIDTH)*/, 1.0); +} diff --git a/part1/ImageProcessing/ImageProcessing/grayscaleFS.glsl b/part1/ImageProcessing/ImageProcessing/grayscaleFS.glsl new file mode 100644 index 0000000..09aaee3 --- /dev/null +++ b/part1/ImageProcessing/ImageProcessing/grayscaleFS.glsl @@ -0,0 +1,10 @@ +varying vec2 v_Texcoords; + +uniform sampler2D u_image; + +void main(void) +{ + const vec3 W = vec3(0.2125, 0.7154, 0.0721); + float luminance = dot(texture2D(u_image, v_Texcoords).rgb, W); + gl_FragColor = vec4(vec3(luminance), 1.0); +} diff --git a/part1/ImageProcessing/ImageProcessing/imageNegativeFS.glsl b/part1/ImageProcessing/ImageProcessing/imageNegativeFS.glsl new file mode 100644 index 0000000..c7daf55 --- /dev/null +++ b/part1/ImageProcessing/ImageProcessing/imageNegativeFS.glsl @@ -0,0 +1,8 @@ +varying vec2 v_Texcoords; + +uniform sampler2D u_image; + +void main(void) +{ + gl_FragColor = vec4(1.0) - texture2D(u_image, v_Texcoords); +} diff --git a/part1/ImageProcessing/ImageProcessing/magentaFS.glsl b/part1/ImageProcessing/ImageProcessing/magentaFS.glsl new file mode 100644 index 0000000..098f3e4 --- /dev/null +++ b/part1/ImageProcessing/ImageProcessing/magentaFS.glsl @@ -0,0 +1,10 @@ +varying vec2 v_Texcoords; + +uniform sampler2D u_image; + +void main(void) +{ + vec3 temp = texture2D(u_image, v_Texcoords).rgb; + + gl_FragColor = vec4(vec3(temp.r, 0.0, temp.b), 1.0); +} diff --git a/part1/ImageProcessing/ImageProcessing/main.cpp b/part1/ImageProcessing/ImageProcessing/main.cpp index 3b1444d..79c768b 100644 --- a/part1/ImageProcessing/ImageProcessing/main.cpp +++ b/part1/ImageProcessing/ImageProcessing/main.cpp @@ -1,146 +1,186 @@ -#include -#include -#include -#include "Utility.h" -#include "SOIL.h" - -int width = 640; -int height = 480; - -GLuint positionLocation = 0; -GLuint texcoordsLocation = 1; -const char *attributeLocations[] = { "Position", "Tex" }; - -GLuint passthroughProgram; -GLuint boxBlurProgram; - -GLuint initShader(const char *vertexShaderPath, const char *fragmentShaderPath) -{ - GLuint program = Utility::createProgram(vertexShaderPath, fragmentShaderPath, attributeLocations, 2); - GLint location; - - glUseProgram(program); - - if ((location = glGetUniformLocation(program, "u_image")) != -1) - { - glUniform1i(location, 0); - } - - if ((location = glGetUniformLocation(program, "u_step")) != -1) - { - glUniform2f(location, 1.0f / (float)width, 1.0f / (float)height); - } - - return program; -} - -void initTextures() -{ - GLuint image = SOIL_load_OGL_texture("Valve.png", 3, 0, 0); - glBindTexture(GL_TEXTURE_2D, image); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); -} - -void initVAO(void) -{ - GLfloat vertices[] = - { - -1.0f, -1.0f, - 1.0f, -1.0f, - 1.0f, 1.0f, - -1.0f, 1.0f, - }; - - GLfloat texcoords[] = - { - 1.0f, 1.0f, - 0.0f, 1.0f, - 0.0f, 0.0f, - 1.0f, 0.0f - }; - - GLushort indices[] = { 0, 1, 3, 3, 1, 2 }; - - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); - - GLuint vertexBufferObjID[3]; - glGenBuffers(3, vertexBufferObjID); - - glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[0]); - glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); - glVertexAttribPointer((GLuint)positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); - glEnableVertexAttribArray(positionLocation); - - glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[1]); - glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords, GL_STATIC_DRAW); - glVertexAttribPointer((GLuint)texcoordsLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); - glEnableVertexAttribArray(texcoordsLocation); - - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBufferObjID[2]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); -} - -void display(void) -{ - glClear(GL_COLOR_BUFFER_BIT); - - // VAO, shader program, and texture already bound - glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); - - glutPostRedisplay(); - glutSwapBuffers(); -} - -void keyboard(unsigned char key, int x, int y) -{ - switch (key) - { - case '1': - glUseProgram(passthroughProgram); - break; - case '2': - glUseProgram(boxBlurProgram); - break; - } -} - -void reshape(int w, int h) -{ - glViewport(0, 0, (GLsizei)w, (GLsizei)h); -} - -int main(int argc, char* argv[]) -{ - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); - glutInitWindowSize(width, height); - glutCreateWindow("Image Processing"); - glewInit(); - GLenum err = glewInit(); - if (GLEW_OK != err) - { - /* Problem: glewInit failed, something is seriously wrong. */ - std::cout << "glewInit failed, aborting." << std::endl; - exit (1); - } - std::cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << std::endl; - std::cout << "OpenGL version " << glGetString(GL_VERSION) << " supported" << std::endl; - - initVAO(); - initTextures(); - passthroughProgram = initShader("passthroughVS.glsl", "passthroughFS.glsl"); - boxBlurProgram = initShader("passthroughVS.glsl", "boxBlurFS.glsl"); - - glutDisplayFunc(display); - glutReshapeFunc(reshape); - glutKeyboardFunc(keyboard); - - glUseProgram(passthroughProgram); - glActiveTexture(GL_TEXTURE0); - - glutMainLoop(); - return 0; +#include +#include +#include +#include "Utility.h" +#include "SOIL.h" + +int width = 640; +int height = 480; + +GLuint positionLocation = 0; +GLuint texcoordsLocation = 1; +const char *attributeLocations[] = { "Position", "Tex" }; + +GLuint passthroughProgram; +GLuint boxBlurProgram; +GLuint imageNegativeProgram; +GLuint gaussianBlurProgram; +GLuint grayscaleProgram; +GLuint edgeDetectionProgram; +GLuint toonShadingProgram; +GLuint blackProgram; +GLuint redProgram; +GLuint magentaProgram; + +GLuint initShader(const char *vertexShaderPath, const char *fragmentShaderPath) +{ + GLuint program = Utility::createProgram(vertexShaderPath, fragmentShaderPath, attributeLocations, 2); + GLint location; + + glUseProgram(program); + + if ((location = glGetUniformLocation(program, "u_image")) != -1) + { + glUniform1i(location, 0); + } + + if ((location = glGetUniformLocation(program, "u_step")) != -1) + { + glUniform2f(location, 1.0f / (float)width, 1.0f / (float)height); + } + + return program; +} + +void initTextures() +{ + GLuint image = SOIL_load_OGL_texture("Valve.png", 3, 0, 0); + glBindTexture(GL_TEXTURE_2D, image); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); +} + +void initVAO(void) +{ + GLfloat vertices[] = + { + -1.0f, -1.0f, + 1.0f, -1.0f, + 1.0f, 1.0f, + -1.0f, 1.0f, + }; + + GLfloat texcoords[] = + { + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f + }; + + GLushort indices[] = { 0, 1, 3, 3, 1, 2 }; + + GLuint vao; + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + GLuint vertexBufferObjID[3]; + glGenBuffers(3, vertexBufferObjID); + + glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[0]); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glVertexAttribPointer((GLuint)positionLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(positionLocation); + + glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObjID[1]); + glBufferData(GL_ARRAY_BUFFER, sizeof(texcoords), texcoords, GL_STATIC_DRAW); + glVertexAttribPointer((GLuint)texcoordsLocation, 2, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(texcoordsLocation); + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vertexBufferObjID[2]); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); +} + +void display(void) +{ + glClear(GL_COLOR_BUFFER_BIT); + + // VAO, shader program, and texture already bound + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0); + + glutPostRedisplay(); + glutSwapBuffers(); +} + +void keyboard(unsigned char key, int x, int y) +{ + switch (key) + { + case '1': + glUseProgram(passthroughProgram); + break; + case '2': + glUseProgram(boxBlurProgram); + break; + case '3': + glUseProgram(imageNegativeProgram); + break; + case '4': + glUseProgram(gaussianBlurProgram); + break; + case '5': + glUseProgram(grayscaleProgram); + break; + case '6': + glUseProgram(edgeDetectionProgram); + break; + case '7': + glUseProgram(toonShadingProgram); + break; + case '8': + glUseProgram(blackProgram); + break; + case '9': + glUseProgram(redProgram); + break; + case '0': + glUseProgram(magentaProgram); + break; + } +} + +void reshape(int w, int h) +{ + glViewport(0, 0, (GLsizei)w, (GLsizei)h); +} + +int main(int argc, char* argv[]) +{ + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA); + glutInitWindowSize(width, height); + glutCreateWindow("Image Processing"); + glewInit(); + GLenum err = glewInit(); + if (GLEW_OK != err) + { + /* Problem: glewInit failed, something is seriously wrong. */ + std::cout << "glewInit failed, aborting." << std::endl; + exit (1); + } + std::cout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << std::endl; + std::cout << "OpenGL version " << glGetString(GL_VERSION) << " supported" << std::endl; + + initVAO(); + initTextures(); + passthroughProgram = initShader("passthroughVS.glsl", "passthroughFS.glsl"); + boxBlurProgram = initShader("passthroughVS.glsl", "boxBlurFS.glsl"); + imageNegativeProgram = initShader("passthroughVS.glsl", "imageNegativeFS.glsl"); + gaussianBlurProgram = initShader("passthroughVS.glsl", "gaussianBlurFS.glsl"); + grayscaleProgram = initShader("passthroughVS.glsl", "grayscaleFS.glsl"); + edgeDetectionProgram = initShader("passthroughVS.glsl", "edgeDetectionFS.glsl"); + toonShadingProgram = initShader("passthroughVS.glsl", "toonShadingFS.glsl"); + blackProgram = initShader("passthroughVS.glsl", "blackFS.glsl"); + redProgram = initShader("passthroughVS.glsl", "redFS.glsl"); + magentaProgram = initShader("passthroughVS.glsl", "magentaFS.glsl"); + + glutDisplayFunc(display); + glutReshapeFunc(reshape); + glutKeyboardFunc(keyboard); + + glUseProgram(passthroughProgram); + glActiveTexture(GL_TEXTURE0); + + glutMainLoop(); + return 0; } \ No newline at end of file diff --git a/part1/ImageProcessing/ImageProcessing/redFS.glsl b/part1/ImageProcessing/ImageProcessing/redFS.glsl new file mode 100644 index 0000000..57a76b7 --- /dev/null +++ b/part1/ImageProcessing/ImageProcessing/redFS.glsl @@ -0,0 +1,10 @@ +varying vec2 v_Texcoords; + +uniform sampler2D u_image; + +void main(void) +{ + vec3 temp = texture2D(u_image, v_Texcoords).rgb; + + gl_FragColor = vec4(vec3(temp.r, 0.0, 0.0), 1.0); +} diff --git a/part1/ImageProcessing/ImageProcessing/toonShadingFS.glsl b/part1/ImageProcessing/ImageProcessing/toonShadingFS.glsl new file mode 100644 index 0000000..9204f8b --- /dev/null +++ b/part1/ImageProcessing/ImageProcessing/toonShadingFS.glsl @@ -0,0 +1,47 @@ +varying vec2 v_Texcoords; + +uniform sampler2D u_image; +uniform vec2 u_step; + +const int KERNEL_WIDTH = 3; // Odd +const float offset = 1.0; + +void main(void) +{ + vec3 accum = vec3(0.0); + const vec3 W = vec3(0.2125, 0.7154, 0.0721); + mat3 sobelH = mat3(vec3(-1,-2,-1),vec3(0,0,0),vec3(1,2,1)); + mat3 sobelV = mat3(vec3(-1,0,1),vec3(-2,0,2),vec3(-1,0,1)); + float luminanceH = 0.0; + float luminanceV = 0.0; + + for (int i = 0; i < KERNEL_WIDTH; ++i) + { + for (int j = 0; j < KERNEL_WIDTH; ++j) + { + vec2 coord = vec2(v_Texcoords.s + ((float(i) - offset) * u_step.s), v_Texcoords.t + ((float(j) - offset) * u_step.t)); + luminanceH += sobelH[i][j] * dot(texture2D(u_image, coord).rgb, W); + luminanceV += sobelV[i][j] * dot(texture2D(u_image, coord).rgb, W); + accum += texture2D(u_image, coord).rgb; + } + } + + vec2 edge = vec2(luminanceH, luminanceV); + float edgeIntensity = length(edge); + + if(edgeIntensity > 0.3) + gl_FragColor = vec4(vec3(0.0), 1.0); + + else + { + float quantize = 0.45;// determine it + vec3 temp = accum * quantize; + temp += vec3(0.5); + ivec3 irgb = ivec3(temp); + temp = vec3(irgb) / quantize; + + gl_FragColor = vec4(temp / float(KERNEL_WIDTH * KERNEL_WIDTH), 1.0); + } + + //gl_FragColor = vec4(vec3(edgeIntensity), 1.0); +} diff --git a/part1/ImageProcessing/SOIL/SOIL.vcxproj.user b/part1/ImageProcessing/SOIL/SOIL.vcxproj.user new file mode 100644 index 0000000..695b5c7 --- /dev/null +++ b/part1/ImageProcessing/SOIL/SOIL.vcxproj.user @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/part2/index.html b/part2/index.html index 1e3f7e2..a74e94c 100644 --- a/part2/index.html +++ b/part2/index.html @@ -1,40 +1,48 @@ - - - - -Vertex Wave - - - - - -
- - - - - - - - - - - + + + + +Vertex Wave + + + + + +
+ + + + + + + + + + + \ No newline at end of file diff --git a/part2/index.js b/part2/index.js index b5df3fb..41e6fc3 100644 --- a/part2/index.js +++ b/part2/index.js @@ -1,151 +1,160 @@ -(function() { - "use strict"; - /*global window,document,Float32Array,Uint16Array,mat4,vec3,snoise*/ - /*global getShaderSource,createWebGLContext,createProgram*/ - - var NUM_WIDTH_PTS = 32; - var NUM_HEIGHT_PTS = 32; - - var message = document.getElementById("message"); - var canvas = document.getElementById("canvas"); - var context = createWebGLContext(canvas, message); - if (!context) { - return; - } - - /////////////////////////////////////////////////////////////////////////// - - context.viewport(0, 0, canvas.width, canvas.height); - context.clearColor(1.0, 1.0, 1.0, 1.0); - context.enable(context.GL_DEPTH_TEST); - - var persp = mat4.create(); - mat4.perspective(45.0, 0.5, 0.1, 100.0, persp); - - var eye = [2.0, 1.0, 3.0]; - var center = [0.0, 0.0, 0.0]; - var up = [0.0, 0.0, 1.0]; - var view = mat4.create(); - mat4.lookAt(eye, center, up, view); - - var positionLocation = 0; - var heightLocation = 1; - var u_modelViewPerspectiveLocation; - - (function initializeShader() { - var program; - var vs = getShaderSource(document.getElementById("vs")); - var fs = getShaderSource(document.getElementById("fs")); - - var program = createProgram(context, vs, fs, message); - context.bindAttribLocation(program, positionLocation, "position"); - u_modelViewPerspectiveLocation = context.getUniformLocation(program,"u_modelViewPerspective"); - - context.useProgram(program); - })(); - - var heights; - var numberOfIndices; - - (function initializeGrid() { - function uploadMesh(positions, heights, indices) { - // Positions - var positionsName = context.createBuffer(); - context.bindBuffer(context.ARRAY_BUFFER, positionsName); - context.bufferData(context.ARRAY_BUFFER, positions, context.STATIC_DRAW); - context.vertexAttribPointer(positionLocation, 2, context.FLOAT, false, 0, 0); - context.enableVertexAttribArray(positionLocation); - - if (heights) - { - // Heights - var heightsName = context.createBuffer(); - context.bindBuffer(context.ARRAY_BUFFER, heightsName); - context.bufferData(context.ARRAY_BUFFER, heights.length * heights.BYTES_PER_ELEMENT, context.STREAM_DRAW); - context.vertexAttribPointer(heightLocation, 1, context.FLOAT, false, 0, 0); - context.enableVertexAttribArray(heightLocation); - } - - // Indices - var indicesName = context.createBuffer(); - context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, indicesName); - context.bufferData(context.ELEMENT_ARRAY_BUFFER, indices, context.STATIC_DRAW); - } - - var WIDTH_DIVISIONS = NUM_WIDTH_PTS - 1; - var HEIGHT_DIVISIONS = NUM_HEIGHT_PTS - 1; - - var numberOfPositions = NUM_WIDTH_PTS * NUM_HEIGHT_PTS; - - var positions = new Float32Array(2 * numberOfPositions); - var indices = new Uint16Array(2 * ((NUM_HEIGHT_PTS * (NUM_WIDTH_PTS - 1)) + (NUM_WIDTH_PTS * (NUM_HEIGHT_PTS - 1)))); - - var positionsIndex = 0; - var indicesIndex = 0; - var length; - - for (var j = 0; j < NUM_WIDTH_PTS; ++j) - { - positions[positionsIndex++] = j /(NUM_WIDTH_PTS - 1); - positions[positionsIndex++] = 0.0; - - if (j>=1) - { - length = positionsIndex / 2; - indices[indicesIndex++] = length - 2; - indices[indicesIndex++] = length - 1; - } - } - - for (var i = 0; i < HEIGHT_DIVISIONS; ++i) - { - var v = (i + 1) / (NUM_HEIGHT_PTS - 1); - positions[positionsIndex++] = 0.0; - positions[positionsIndex++] = v; - - length = (positionsIndex / 2); - indices[indicesIndex++] = length - 1; - indices[indicesIndex++] = length - 1 - NUM_WIDTH_PTS; - - for (var k = 0; k < WIDTH_DIVISIONS; ++k) - { - positions[positionsIndex++] = (k + 1) / (NUM_WIDTH_PTS - 1); - positions[positionsIndex++] = v; - - length = positionsIndex / 2; - var new_pt = length - 1; - indices[indicesIndex++] = new_pt - 1; // Previous side - indices[indicesIndex++] = new_pt; - - indices[indicesIndex++] = new_pt - NUM_WIDTH_PTS; // Previous bottom - indices[indicesIndex++] = new_pt; - } - } - - uploadMesh(positions, heights, indices); - numberOfIndices = indices.length; - })(); - - (function animate(){ - /////////////////////////////////////////////////////////////////////////// - // Update - - var model = mat4.create(); - mat4.identity(model); - mat4.translate(model, [-0.5, -0.5, 0.0]); - var mv = mat4.create(); - mat4.multiply(view, model, mv); - var mvp = mat4.create(); - mat4.multiply(persp, mv, mvp); - - /////////////////////////////////////////////////////////////////////////// - // Render - context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT); - - context.uniformMatrix4fv(u_modelViewPerspectiveLocation, false, mvp); - context.drawElements(context.LINES, numberOfIndices, context.UNSIGNED_SHORT,0); - - window.requestAnimFrame(animate); - })(); - -}()); +(function() { + "use strict"; + /*global window,document,Float32Array,Uint16Array,mat4,vec3,snoise*/ + /*global getShaderSource,createWebGLContext,createProgram*/ + + var NUM_WIDTH_PTS = 32; + var NUM_HEIGHT_PTS = 32; + + var message = document.getElementById("message"); + var canvas = document.getElementById("canvas"); + var context = createWebGLContext(canvas, message); + if (!context) { + return; + } + + /////////////////////////////////////////////////////////////////////////// + + context.viewport(0, 0, canvas.width, canvas.height); + context.clearColor(1.0, 1.0, 1.0, 1.0); + context.enable(context.GL_DEPTH_TEST); + + var persp = mat4.create(); + mat4.perspective(45.0, 0.5, 0.1, 100.0, persp); + + var eye = [2.0, 1.0, 3.0]; + var center = [0.0, 0.0, 0.0]; + var up = [0.0, 0.0, 1.0]; + var view = mat4.create(); + mat4.lookAt(eye, center, up, view); + + var positionLocation = 0; + var heightLocation = 1; + var u_modelViewPerspectiveLocation; + + var u_timeLocation; + var delta = 0.0; + + (function initializeShader() { + var program; + var vs = getShaderSource(document.getElementById("vs")); + var fs = getShaderSource(document.getElementById("fs")); + + var program = createProgram(context, vs, fs, message); + context.bindAttribLocation(program, positionLocation, "position"); + u_modelViewPerspectiveLocation = context.getUniformLocation(program,"u_modelViewPerspective"); + + u_timeLocation = context.getUniformLocation(program,"u_time"); + + context.useProgram(program); + })(); + + var heights; + var numberOfIndices; + + (function initializeGrid() { + function uploadMesh(positions, heights, indices) { + // Positions + var positionsName = context.createBuffer(); + context.bindBuffer(context.ARRAY_BUFFER, positionsName); + context.bufferData(context.ARRAY_BUFFER, positions, context.STATIC_DRAW); + context.vertexAttribPointer(positionLocation, 2, context.FLOAT, false, 0, 0); + context.enableVertexAttribArray(positionLocation); + + if (heights) + { + // Heights + var heightsName = context.createBuffer(); + context.bindBuffer(context.ARRAY_BUFFER, heightsName); + context.bufferData(context.ARRAY_BUFFER, heights.length * heights.BYTES_PER_ELEMENT, context.STREAM_DRAW); + context.vertexAttribPointer(heightLocation, 1, context.FLOAT, false, 0, 0); + context.enableVertexAttribArray(heightLocation); + } + + // Indices + var indicesName = context.createBuffer(); + context.bindBuffer(context.ELEMENT_ARRAY_BUFFER, indicesName); + context.bufferData(context.ELEMENT_ARRAY_BUFFER, indices, context.STATIC_DRAW); + } + + var WIDTH_DIVISIONS = NUM_WIDTH_PTS - 1; + var HEIGHT_DIVISIONS = NUM_HEIGHT_PTS - 1; + + var numberOfPositions = NUM_WIDTH_PTS * NUM_HEIGHT_PTS; + + var positions = new Float32Array(2 * numberOfPositions); + var indices = new Uint16Array(2 * ((NUM_HEIGHT_PTS * (NUM_WIDTH_PTS - 1)) + (NUM_WIDTH_PTS * (NUM_HEIGHT_PTS - 1)))); + + var positionsIndex = 0; + var indicesIndex = 0; + var length; + + for (var j = 0; j < NUM_WIDTH_PTS; ++j) + { + positions[positionsIndex++] = j /(NUM_WIDTH_PTS - 1); + positions[positionsIndex++] = 0.0; + + if (j>=1) + { + length = positionsIndex / 2; + indices[indicesIndex++] = length - 2; + indices[indicesIndex++] = length - 1; + } + } + + for (var i = 0; i < HEIGHT_DIVISIONS; ++i) + { + var v = (i + 1) / (NUM_HEIGHT_PTS - 1); + positions[positionsIndex++] = 0.0; + positions[positionsIndex++] = v; + + length = (positionsIndex / 2); + indices[indicesIndex++] = length - 1; + indices[indicesIndex++] = length - 1 - NUM_WIDTH_PTS; + + for (var k = 0; k < WIDTH_DIVISIONS; ++k) + { + positions[positionsIndex++] = (k + 1) / (NUM_WIDTH_PTS - 1); + positions[positionsIndex++] = v; + + length = positionsIndex / 2; + var new_pt = length - 1; + indices[indicesIndex++] = new_pt - 1; // Previous side + indices[indicesIndex++] = new_pt; + + indices[indicesIndex++] = new_pt - NUM_WIDTH_PTS; // Previous bottom + indices[indicesIndex++] = new_pt; + } + } + + uploadMesh(positions, heights, indices); + numberOfIndices = indices.length; + })(); + + (function animate(){ + /////////////////////////////////////////////////////////////////////////// + // Update + + var model = mat4.create(); + mat4.identity(model); + mat4.translate(model, [-0.5, -0.5, 0.0]); + var mv = mat4.create(); + mat4.multiply(view, model, mv); + var mvp = mat4.create(); + mat4.multiply(persp, mv, mvp); + + delta += 0.01; + + /////////////////////////////////////////////////////////////////////////// + // Render + context.clear(context.COLOR_BUFFER_BIT | context.DEPTH_BUFFER_BIT); + + context.uniformMatrix4fv(u_modelViewPerspectiveLocation, false, mvp); + context.drawElements(context.LINES, numberOfIndices, context.UNSIGNED_SHORT,0); + + context.uniform1f(u_timeLocation, delta); + + window.requestAnimFrame(animate); + })(); + +}()); diff --git a/part2/index_custom.html b/part2/index_custom.html new file mode 100644 index 0000000..08fb516 --- /dev/null +++ b/part2/index_custom.html @@ -0,0 +1,49 @@ + + + + +Vertex Wave + + + + + +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/part2/index_simplex.html b/part2/index_simplex.html new file mode 100644 index 0000000..df6ef63 --- /dev/null +++ b/part2/index_simplex.html @@ -0,0 +1,92 @@ + + + + +Vertex Wave + + + + + +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/readmeFiles/Thumbs.db b/readmeFiles/Thumbs.db new file mode 100644 index 0000000..14030ed Binary files /dev/null and b/readmeFiles/Thumbs.db differ