diff --git a/core/Light.cpp b/core/Light.cpp new file mode 100644 index 0000000..39f7e56 --- /dev/null +++ b/core/Light.cpp @@ -0,0 +1,21 @@ +#include "Light.h" + +Name Light::GetType() const {return "Light";} + +Name DirectionalLight::GetType() const {return "DirectionalLight";} + +DirectionalLight::DirectionalLight() { + this->direction = Vector3(0.0f); + this->color = Vector3(0.0f); + this->ambient = 0.0f; + this->diffuse = 0.0f; + this->specular = 0.0f; +} + +DirectionalLight::DirectionalLight(Vector3 direction, Vector3 color, cfloat ambient, cfloat diffuse, cfloat specular) { + this->direction = direction; + this->color = color; + this->ambient = ambient; + this->diffuse = diffuse; + this->specular = specular; +} diff --git a/core/Light.h b/core/Light.h new file mode 100644 index 0000000..8a9be98 --- /dev/null +++ b/core/Light.h @@ -0,0 +1,22 @@ +#ifndef LIGHT_H +#define LIGHT_H + +#include "types.h" +#include "Spatial.h" + +class Light : public Spatial { +public: + Vector3 color; + cfloat ambient, diffuse, specular; + virtual Name GetType() const; +}; + +class DirectionalLight : public Light { +public: + Vector3 direction; + DirectionalLight(); + DirectionalLight(Vector3 direction, Vector3 color, cfloat ambient, cfloat diffuse, cfloat specular); + virtual Name GetType() const; +}; + +#endif /* LIGHT_H */ diff --git a/core/Material.cpp b/core/Material.cpp index c49dbbd..d2b2020 100644 --- a/core/Material.cpp +++ b/core/Material.cpp @@ -42,4 +42,5 @@ Material::Material() { usesColor = false; usesTex = false; alphaScissor = 0.0f; + unshaded = false; } diff --git a/core/Material.h b/core/Material.h index 4e9a322..36a3c54 100644 --- a/core/Material.h +++ b/core/Material.h @@ -27,6 +27,7 @@ struct Material { Texture tex; bool usesTex; cfloat alphaScissor; + bool unshaded; Material(); }; diff --git a/core/Mesh.cpp b/core/Mesh.cpp index e3513d9..52a6641 100644 --- a/core/Mesh.cpp +++ b/core/Mesh.cpp @@ -24,10 +24,12 @@ void SubMesh::SetupSubMesh() { // Vertex positions glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) 0); - // Vertex UV + // Vertex normal glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(3 * sizeof(float))); - // TODO normals + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (3 * sizeof(float))); + // Vertex UV + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (6 * sizeof(float))); glBindVertexArray(0); } @@ -36,11 +38,14 @@ void SubMesh::Draw(Shader *shader) { shader->UpdateColor(material.usesColor, material.color); shader->UpdateTex(material.usesTex, material.tex); shader->UpdateAlphaScissor(material.alphaScissor); + shader->UpdateUnshaded(material.unshaded); glBindVertexArray(VAO); glDrawElements(GL_TRIANGLES, indices.size() * 3, GL_UNSIGNED_INT, 0); glBindVertexArray(0); } +Name Mesh::GetType() const {return "Mesh";} + Mesh::Mesh() {} Mesh::~Mesh() { @@ -94,8 +99,11 @@ SubMesh *Mesh::aiMesh2SubMesh(aiMesh *aimesh){ SubMesh *sub = new SubMesh(); for (int i = 0; i < aimesh->mNumVertices; i++) { aiVector3D aiPosition = aimesh->mVertices[i]; + aiVector3D aiNormal = aimesh->mNormals[i]; aiVector3D aiUV = aimesh->mTextureCoords[0][i]; // TODO get ALL texture coords - Vertex vertex(aiPosition.x, aiPosition.y, aiPosition.z, aiUV.x, aiUV.y); + Vertex vertex(aiPosition.x, aiPosition.y, aiPosition.z, + aiNormal.x, aiNormal.y, aiNormal.z, + aiUV.x, aiUV.y); sub->vertices.push_back(vertex); } for (int i = 0; i < aimesh->mNumFaces; i++) { diff --git a/core/Mesh.h b/core/Mesh.h index 12facfa..58b8364 100644 --- a/core/Mesh.h +++ b/core/Mesh.h @@ -43,6 +43,7 @@ public: static Mesh *FromFile(const char *filename); virtual bool IsDrawable() const {return true;} virtual void Draw(Shader *shader); + virtual Name GetType() const; protected: SubMeshList submeshes; virtual void SetupMesh(); diff --git a/core/Node.cpp b/core/Node.cpp index 2a49360..c8a5f40 100644 --- a/core/Node.cpp +++ b/core/Node.cpp @@ -1,5 +1,7 @@ #include "Node.h" +Name Node::GetType() const {return "Node";} + Node *Node::root = {new Node()}; Node *Node::GetRoot() { return root; diff --git a/core/Node.h b/core/Node.h index a5910ec..5a4364e 100644 --- a/core/Node.h +++ b/core/Node.h @@ -3,6 +3,8 @@ #include +#include "types.h" + class Node; // Forwards declare class NodeList : public std::vector { public: @@ -16,6 +18,7 @@ public: virtual bool IsDrawable() const; virtual void Draw(){}; virtual bool IsTransformable() const; + virtual Name GetType() const; private: static Node *root; }; diff --git a/core/Screen.cpp b/core/Screen.cpp index 8f6dcb6..71154bd 100644 --- a/core/Screen.cpp +++ b/core/Screen.cpp @@ -23,9 +23,12 @@ Screen::Screen() { // Vertex positions glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) 0); - //Vertex UV + // Vertex Normals glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (3 * sizeof(float))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (3 * sizeof(float))); + //Vertex UV + glEnableVertexAttribArray(2); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) (6 * sizeof(float))); glBindVertexArray(0); diff --git a/core/Shaders/Shader.cpp b/core/Shaders/Shader.cpp index 0278ea5..e827dfb 100644 --- a/core/Shaders/Shader.cpp +++ b/core/Shaders/Shader.cpp @@ -72,6 +72,18 @@ void Shader::UpdateTex(bool usesTex, Texture tex) { void Shader::UpdateAlphaScissor(cfloat alphaScissor) { glUniform1f(glGetUniformLocation(id, "material.alphaScissor"), alphaScissor); } +void Shader::UpdateUnshaded(bool unshaded) { + glUniform1i(glGetUniformLocation(id, "material.unshaded"), (int) unshaded); +} + +void Shader::UpdateDirectionalLight(DirectionalLight directionalLight) { + glUniform3fv(glGetUniformLocation(id, "directionalLight.direction"), 1, glm::value_ptr(directionalLight.direction)); + glUniform3fv(glGetUniformLocation(id, "directionalLight.color"), 1, glm::value_ptr(directionalLight.color)); + + glUniform1f(glGetUniformLocation(id, "directionalLight.ambient"), directionalLight.ambient); + glUniform1f(glGetUniformLocation(id, "directionalLight.diffuse"), directionalLight.diffuse); + glUniform1f(glGetUniformLocation(id, "directionalLight.specular"), directionalLight.specular); +} Name Shader::GetName() const { return "Unnamed Shader"; diff --git a/core/Shaders/Shader.h b/core/Shaders/Shader.h index f190066..c08d796 100644 --- a/core/Shaders/Shader.h +++ b/core/Shaders/Shader.h @@ -5,6 +5,7 @@ #include "types.h" #include "Material.h" +#include "Light.h" class Shader { public: @@ -20,6 +21,9 @@ public: void UpdateTex(bool usesTex); void UpdateTex(bool usesTex, Texture tex); void UpdateAlphaScissor(cfloat alphaScissor); + void UpdateUnshaded(bool unshaded); + + void UpdateDirectionalLight(DirectionalLight directionalLight); virtual Name GetName() const; }; diff --git a/core/Spatial.cpp b/core/Spatial.cpp new file mode 100644 index 0000000..ac8ddae --- /dev/null +++ b/core/Spatial.cpp @@ -0,0 +1,3 @@ +#include "Spatial.h" + +Name Spatial::GetType() const {return "Spatial";} diff --git a/core/Spatial.h b/core/Spatial.h index 91d975e..49766fa 100644 --- a/core/Spatial.h +++ b/core/Spatial.h @@ -8,6 +8,7 @@ class Spatial : public Node { public: Transform transform; virtual bool IsTransformable() const { return true;} + virtual Name GetType() const; }; #endif /* SPATIAL_H */ diff --git a/core/Util.h b/core/Util.h index 64581a9..6774ce2 100644 --- a/core/Util.h +++ b/core/Util.h @@ -5,10 +5,28 @@ #include #include +#include "types.h" +#include "Node.h" + namespace Util { void Die(const char *msg); void Die(const char * msg, const char * more); void Die(std::string msg); + + template + T* FindNodeByType(Node *&root, const Name &type) { + if (root->GetType() == type) { + return dynamic_cast(root); + } + + for (Node *child : root->children) { + T* res = FindNodeByType(child, type); + if (res) { + return res; + } + } + return nullptr; + } } #endif /* UTIL_H */ diff --git a/core/Vertex.cpp b/core/Vertex.cpp index eb6c5e9..6c57e3a 100644 --- a/core/Vertex.cpp +++ b/core/Vertex.cpp @@ -4,6 +4,9 @@ Vertex::Vertex() { x = 0.0f; y = 0.0f; z = 0.0f; + nx = 0.0f; + ny = 0.0f; + nz = 0.0f; u = 0.0f; v = 0.0f; } @@ -12,6 +15,9 @@ Vertex::Vertex(cfloat x, cfloat y, cfloat z) { this->x = x; this->y = y; this->z = z; + this->nz = 0.0f; + this->ny = 0.0f; + this->nz = 0.0f; this->u = 0.0f; this->v = 0.0f; } @@ -20,6 +26,22 @@ Vertex::Vertex(cfloat x, cfloat y, cfloat z, cfloat u, cfloat v) { this->x = x; this->y = y; this->z = z; + this->nx = 0.0f; + this->ny = 0.0f; + this->nz = 0.0f; + this->u = u; + this->v = v; +} + +Vertex::Vertex(cfloat x, cfloat y, cfloat z, + cfloat nx, float ny, cfloat nz, + cfloat u, cfloat v) { + this->x = x; + this->y = y; + this->z = z; + this->nx = nx; + this->ny = ny; + this->nz = nz; this->u = u; this->v = v; } diff --git a/core/Vertex.h b/core/Vertex.h index 1d39081..0cd337f 100644 --- a/core/Vertex.h +++ b/core/Vertex.h @@ -9,7 +9,11 @@ struct Vertex { Vertex(); Vertex(cfloat x, cfloat y, cfloat z); Vertex(cfloat x, cfloat y, cfloat z, cfloat u, cfloat v); + Vertex(cfloat x, cfloat y, cfloat z, + cfloat nx, float ny, cfloat nz, + cfloat u, cfloat v); cfloat x, y, z; + cfloat nx, ny, nz; cfloat u, v; }; diff --git a/core/couch.cpp b/core/couch.cpp index 0173b3b..ace6bce 100644 --- a/core/couch.cpp +++ b/core/couch.cpp @@ -8,6 +8,8 @@ #include "types.h" +#include "Util.h" + #include "Shaders/FlatShader.h" #include "Shaders/ScreenShader.h" @@ -17,6 +19,7 @@ #include "Input.h" #include "Node.h" #include "Mesh.h" +#include "Light.h" #include "Scripting/Lua.h" // Thirdparty Includes @@ -49,7 +52,6 @@ void render(Node *curr, Shader *shader, Matrix model) { } } - int main() { int err; @@ -113,6 +115,15 @@ int main() { view = glm::translate(view, -camera->transform.position); shader->UpdateView(view); + // Find the lights + DirectionalLight *dirLight = Util::FindNodeByType(root, "DirectionalLight"); + if (dirLight) { + shader->UpdateDirectionalLight(*dirLight); + } else { + // No light in scene + shader->UpdateDirectionalLight(DirectionalLight()); + } + // Render the scene tree render(root, shader, Matrix(1.0f)); diff --git a/core/types.h b/core/types.h index 8d9c6a7..1e6a035 100644 --- a/core/types.h +++ b/core/types.h @@ -1,8 +1,8 @@ #ifndef TYPES_H #define TYPES_H -#include #include +#include #include #include diff --git a/demo/main.lua b/demo/main.lua index 45148da..cf8ecfb 100644 --- a/demo/main.lua +++ b/demo/main.lua @@ -17,12 +17,21 @@ local SPEED = 30 local RED = couch.Color(1.0, 0.0, 0.0) local BLUE = couch.Color(0.0, 0.0, 1.0) +local light + function init() local material camera = couch.Camera() camera:MakeCurrent() camera.transform:Translate(0.0, 0.0, 10.0) + + light = couch.DirectionalLight.new() + light.direction = couch.Vector3(0.0, 0.0, -1.0) + light.color = couch.Vector3(1.0, 1.0, 1.0) + light.ambient = 0.4 + light.diffuse = 1.0 + couch.Node.GetRoot().children:Append(light) ball = couch.Mesh.FromFile("cube.glb") material = couch.Material() @@ -101,6 +110,12 @@ function onkey(key, code, action, mod) elseif (key == couch.KEY_D or key == couch.KEY_A) and action == couch.ACTION_RELEASE then vx = 0.0 end + + if key == couch.KEY_DOWN and action == couch.ACTION_PRESS then + light.ambient = light.ambient - 0.1 + elseif key == couch.KEY_UP and action == couch.ACTION_PRESS then + light.ambient = light.ambient + 0.1 + end end function onmousemotion(_, _, relx, rely) diff --git a/roadmap.md b/roadmap.md index 5ec425c..eabd222 100644 --- a/roadmap.md +++ b/roadmap.md @@ -48,7 +48,13 @@ swig files and customizing the interface by hand. I also want to add a whole mes so that I don't have to test for keypresses. Lastly, I want to test if a function exists before calling it from the lua file, so stubs aren't necessary to prevent a crash -- [ ] Combine files -- [ ] Better interface -- [ ] Constants for keys and the like -- [ ] No crash on calling non-existant scripting hooks +- [X] Combine files +- [X] Better interface +- [X] Constants for keys and the like +- [X] No crash on calling non-existant scripting hooks + +## Lighting + +I'm a bit happier with the system now, I think it's time I started the lighting. +We're going to use a pretty basic Phong lighting system, with +Flat and Garourd shaders available (This was all that was available on the PSX!) diff --git a/scripting/couch.i b/scripting/couch.i index 9a75359..bb23ad2 100644 --- a/scripting/couch.i +++ b/scripting/couch.i @@ -14,6 +14,7 @@ #include "Mesh.h" #include "Material.h" #include "Camera.h" +#include "Light.h" %} %rename("%(strip:[script_])s") ""; @@ -24,6 +25,7 @@ typedef float cfloat; class Vector3 { public: Vector3(); + Vector3(cfloat x, cfloat y, cfloat z); cfloat x, y, z; }; @@ -37,6 +39,13 @@ public: } %ignore "Vector3"; +%extend DirectionalLight { + static DirectionalLight* script_new() { + return new DirectionalLight(); + } +} + + %include "types.h" %include "constants.h" %include "Node.h" @@ -45,4 +54,5 @@ public: %include "Transform.h" %include "Material.h" %include "Camera.h" +%include "Light.h" diff --git a/shaders/flat.frag b/shaders/flat.frag index f347399..f099139 100644 --- a/shaders/flat.frag +++ b/shaders/flat.frag @@ -1,6 +1,7 @@ #version 330 core in vec3 UV; +in vec3 NORMAL; out vec4 FragColor; @@ -10,9 +11,19 @@ struct Material { sampler2D tex; bool usesTex; float alphaScissor; + bool unshaded; +}; + +struct DirectionalLight { + vec3 direction; + vec3 color; + float ambient; + float diffuse; + float specular; }; uniform Material material; +uniform DirectionalLight directionalLight; void main() { FragColor = vec4(0.0); @@ -25,4 +36,10 @@ void main() { if (FragColor.w < material.alphaScissor) { discard; } + + if (!material.unshaded) { + vec3 ambient = directionalLight.ambient * directionalLight.color; + vec3 diffuse = directionalLight.diffuse * reflect(directionalLight.direction, NORMAL) * directionalLight.color; + FragColor *= vec4(ambient, 1.0); + } } diff --git a/shaders/flat.vert b/shaders/flat.vert index e1fb98a..0c248b6 100644 --- a/shaders/flat.vert +++ b/shaders/flat.vert @@ -1,16 +1,19 @@ #version 330 core layout (location = 0) in vec3 pos; -layout (location = 1) in vec2 uv; +layout (location = 1) in vec3 normal; +layout (location = 2) in vec2 uv; uniform mat4 MODEL; uniform mat4 VIEW; uniform mat4 PROJECTION; out vec3 UV; +out vec3 NORMAL; void main() { vec4 vertex = PROJECTION * VIEW * MODEL * vec4(pos, 1.0); gl_Position = vertex; UV = vec3(uv * vertex.z, vertex.z); + NORMAL = normal; } diff --git a/shaders/screen.vert b/shaders/screen.vert index 0f1317d..37c17bb 100644 --- a/shaders/screen.vert +++ b/shaders/screen.vert @@ -1,7 +1,8 @@ #version 330 core layout (location = 0) in vec3 pos; -layout (location = 1) in vec2 uv; +layout (location = 1) in vec3 normal; +layout (location = 2) in vec2 uv; out vec2 UV;