summaryrefslogtreecommitdiffstats
path: root/dev/MinGfx/src/default_shader.h
diff options
context:
space:
mode:
Diffstat (limited to 'dev/MinGfx/src/default_shader.h')
-rw-r--r--dev/MinGfx/src/default_shader.h168
1 files changed, 168 insertions, 0 deletions
diff --git a/dev/MinGfx/src/default_shader.h b/dev/MinGfx/src/default_shader.h
new file mode 100644
index 0000000..677acae
--- /dev/null
+++ b/dev/MinGfx/src/default_shader.h
@@ -0,0 +1,168 @@
+/*
+ This file is part of the MinGfx Project.
+
+ Copyright (c) 2017,2018 Regents of the University of Minnesota.
+ All Rights Reserved.
+
+ Original Author(s) of this File:
+ Dan Keefe, 2018, University of Minnesota
+
+ Author(s) of Significant Updates/Modifications to the File:
+ ...
+ */
+
+#ifndef SRC_DEFAULT_SHADER_H_
+#define SRC_DEFAULT_SHADER_H_
+
+#include "color.h"
+#include "point3.h"
+#include "shader_program.h"
+#include "texture2d.h"
+#include "vector3.h"
+#include "matrix4.h"
+#include "mesh.h"
+
+
+
+namespace mingfx {
+
+/** A simple GLSL shader for textured per-fragment Phong shading with multiple
+ light sources. This can be used to draw 3D models stored in a mingfx::Mesh
+ data structure or you can use it with your own geometry data structures.
+ Lighting properties are stored within the class itself since these are considered
+ part of the shading model. Material properties are considered properties of the
+ meshes or other materials you wish to draw so these are stored outside of the
+ class and passed into the Draw() or UseProgram() functions.
+
+ An example of using DefaultShader to render a mesh:
+ ~~~
+ DefaultShader phong_shader;
+ Mesh teapot;
+ DefaultShader::MaterialProperties teapot_material;
+
+ void Init() {
+ // initialize the shader
+ DefaultShader::LightProperties red_light;
+ red_light.position = Point3(-10, 5, 5);
+ red_light.diffuseIntensity = Color(1,0,0);
+ phong_shader.AddLight(red_light);
+
+ // initialize the mesh
+ teapot.LoadFromOBJ(Platform::FindMinGfxDataFile("teapot.obj"));
+ }
+
+ void DrawUsingOpenGL() {
+ Matrix4 M;
+ Matrix4 V = Matrix4::LookAt(Point3(0,0,3), Point3(0,0,0), Vector3(0,1,0));
+ Matrix4 P = Matrix4::Perspective(60.0, aspect_ratio(), 0.1, 10.0);
+ phong_shader.Draw(M, V, P, teapot, teapot_material);
+ }
+ ~~~
+ */
+class DefaultShader {
+public:
+
+ /// If changed, this needs to also be changed in the glsl shader code
+ static const unsigned int MAX_LIGHTS = 10;
+
+
+ /// Small data structure to hold properties of the material to be lit
+ class MaterialProperties {
+ public:
+ Color ambient_reflectance;
+ Color diffuse_reflectance;
+ Color specular_reflectance;
+ float shinniness;
+ Texture2D surface_texture;
+ // eventually, this might include a normal map, etc.
+
+ // defaults
+ MaterialProperties() :
+ ambient_reflectance(0.25f, 0.25f, 0.25f),
+ diffuse_reflectance(0.6f, 0.6f, 0.6f),
+ specular_reflectance(0.4f, 0.4f, 0.4f),
+ shinniness(20.0f) {}
+ };
+
+ /// Small data structure to hold per-light properties
+ class LightProperties {
+ public:
+ Point3 position;
+ Color ambient_intensity;
+ Color diffuse_intensity;
+ Color specular_intensity;
+
+ // defaults
+ LightProperties() :
+ position(10.0f, 10.0f, 10.0f),
+ ambient_intensity(0.25f, 0.25f, 0.25f),
+ diffuse_intensity(0.6f, 0.6f, 0.6f),
+ specular_intensity(0.6f, 0.6f, 0.6f) {}
+ };
+
+ /// The constructor defaults to adding a single white light to the scene at
+ /// (10,10,10). Change this by passing it 'false'. The constructor does
+ /// not load and compile the shader right away. This is done inside Init().
+ DefaultShader(bool add_default_light=true);
+
+ virtual ~DefaultShader();
+
+ /// Multiple lights are supported, this adds one to the end of the list.
+ /// Up to MAX_LIGHTS can be added.
+ void AddLight(LightProperties light);
+
+ /// Changes the properties for a light that was already added.
+ void SetLight(int i, LightProperties light);
+
+
+ /// This loads vertex and fragment shaders from files, compiles them, and
+ /// links them. So, it must be called from within an active OpenGL context,
+ /// for example, from within GraphicsApp::Init() or GraphicsApp::DrawUsingOpenGL().
+ /// If you call Draw() before calling Init(), then Init() will be called as
+ /// the first step within Draw(). So, if you do not mind a slowdown on the
+ /// very first frame of your program, it is fine to skip calling Init().
+ void Init();
+
+ /// This starts the shader and sets its uniform variables based upon the
+ /// current set of lights, the material properties passed in, and the
+ /// model, view, and projection matrices. Then, it calls mesh->Draw().
+ /// After drawing, it disables the shader.
+ void Draw(const Matrix4 &model, const Matrix4 &view, const Matrix4 &projection,
+ Mesh *mesh, const MaterialProperties &material);
+
+
+ /// Only needed if you do not want to draw a Mesh.
+ /// This does all of the same setup for drawing that the Draw() function does
+ /// and then it returns so that you may draw your own geometry however you want.
+ /// After doing your draw must call StopProgram() to turn off the shader.
+ void UseProgram(const Matrix4 &model, const Matrix4 &view, const Matrix4 &projection,
+ const MaterialProperties &material);
+
+ /// Only needed if you do not want to draw a Mesh. Call this after UseProgram()
+ /// and after drawing your geometry to turn off the shader.
+ void StopProgram();
+
+
+ int num_lights();
+
+ LightProperties light(int i);
+
+
+private:
+
+ std::vector<LightProperties> lights_;
+
+ // cached raw float arrays store data to send directly to the gpu
+ // GLSL requires fixed size arrays for these
+ float lightPositions_[3*MAX_LIGHTS];
+ float lightIas_[4*MAX_LIGHTS];
+ float lightIds_[4*MAX_LIGHTS];
+ float lightIss_[4*MAX_LIGHTS];
+ void update_light_arrays();
+
+ ShaderProgram phongShader_;
+};
+
+} // end namespace
+
+#endif \ No newline at end of file