diff --git a/depthMap.frag b/depthMap.frag index bf9ac1d..acdc33c 100644 --- a/depthMap.frag +++ b/depthMap.frag @@ -1,3 +1,15 @@ #version 330 core -void main(){} +uniform float farPlane; +uniform bool point; +uniform vec3 lightPos; + +in vec4 fragPos; + +void main(){ + if(point){ + float dist=length(lightPos-fragPos.xyz); + dist/=farPlane; + gl_FragDepth=dist; + } +} diff --git a/depthMap.geo b/depthMap.geo new file mode 100644 index 0000000..9b07a0e --- /dev/null +++ b/depthMap.geo @@ -0,0 +1,22 @@ +#version 330 core + +layout (triangles) in; +layout (triangle_strip, max_vertices=18) out; + +out vec4 fragPos; + +uniform mat4 shadowMat[6]; +uniform bool point; + +void main(){ + if(point) + for(int i=0;i<6;i++){ + gl_Layer=i; + for(int j=0;j<3;j++){ + fragPos=gl_in[j].gl_Position; + gl_Position=shadowMat[i]*fragPos; + EmitVertex(); + } + EndPrimitive(); + } +} diff --git a/depthMap.vert b/depthMap.vert index 7db42c5..6758f1c 100644 --- a/depthMap.vert +++ b/depthMap.vert @@ -4,7 +4,11 @@ layout (location=0) in vec3 aPos; uniform mat4 model; uniform mat4 lightMat; +uniform bool point; void main(){ - gl_Position=lightMat*model*vec4(aPos,1); + if(point) + gl_Position=model*vec4(aPos,1); + else + gl_Position=lightMat*model*vec4(aPos,1); } diff --git a/light.cpp b/light.cpp index d9d39d3..9ccba16 100755 --- a/light.cpp +++ b/light.cpp @@ -15,23 +15,31 @@ using namespace glm; using namespace std; namespace vb01{ - Light::Light(){ + Light::Light(Type t){ + this->type=t; + string basePath="../../vb01/depthMap."; + glGenFramebuffers(1,&depthmapFBO); - - depthMap=new Texture(depthMapSize,depthMapSize); - glBindFramebuffer(GL_FRAMEBUFFER,depthmapFBO); - glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,*(depthMap->getTexture()),0); + if(this->type==POINT){ + depthMap=new Texture(depthMapSize); + glFramebufferTexture(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,*(depthMap->getTexture()),0); + depthMapShader=new Shader(basePath+"vert",basePath+"frag",basePath+"geo"); + } + else{ + depthMap=new Texture(depthMapSize,depthMapSize,true); + glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,*(depthMap->getTexture()),0); + depthMapShader=new Shader(basePath+"vert",basePath+"frag"); + } glDrawBuffer(GL_NONE); glReadBuffer(GL_NONE); glBindFramebuffer(GL_FRAMEBUFFER,0); + if(glCheckFramebufferStatus(GL_FRAMEBUFFER)!=GL_FRAMEBUFFER_COMPLETE) cout<<"Not complete\n"; else cout<<"Complete\n"; - string basePath="../../vb01/depthMap."; - depthMapShader=new Shader(basePath+"vert",basePath+"frag"); } Light::~Light(){ @@ -66,89 +74,102 @@ namespace vb01{ for(Mesh *m : d->getMeshes()) materials.push_back(m->getMaterial()); } - for(int i=0;i meshes=n->getMeshes(); for(Mesh *mesh : meshes){ Material *mat=mesh->getMaterial(); if(n->isVisible()&&mat&&mat->isLightingEnabled()){ - mat4 proj,view; + Vector3 pos=n->getWorldPosition(); + Quaternion rot=n->getWorldOrientation(); + Vector3 rotAxis=rot.norm().getAxis(); + + if(rotAxis==Vector3::VEC_ZERO) + rotAxis=Vector3::VEC_I; + + Vector3 upDir=direction.cross(Vector3(0,1,0)); + if(upDir==Vector3(0,0,0)) + upDir=Vector3::VEC_I; + + vec3 dir=vec3(direction.x,direction.y,direction.z); + vec3 up=vec3(upDir.x,upDir.y,upDir.z); + vec3 p=type==DIRECTIONAL?vec3(pos.x,pos.y,pos.z)-.5f*farPlane*dir:vec3(position.x,position.y,position.z); + view=lookAt(p,p+dir,up); + proj=(type==DIRECTIONAL?ortho(-10.f,10.f,-10.f,10.f,nearPlane,farPlane):perspective(radians(90.f),1.f,nearPlane,farPlane)); + mat4 model=translate(mat4(1.f),vec3(pos.x,pos.y,pos.z)); + model=rotate(model,rot.getAngle(),vec3(rotAxis.x,rotAxis.y,rotAxis.z)); + if(mesh->isCastShadow()){ - Vector3 pos=n->getWorldPosition(); - Quaternion rot=n->getWorldOrientation(); - Vector3 rotAxis=rot.norm().getAxis(); - - if(rotAxis==Vector3::VEC_ZERO) - rotAxis=Vector3::VEC_I; - - glViewport(0,0,depthMapSize,depthMapSize); - glBindFramebuffer(GL_FRAMEBUFFER,depthmapFBO); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - - Vector3 upDir=direction.cross(Vector3(0,1,0)); - if(upDir==Vector3(0,0,0)) - upDir=Vector3::VEC_I; - - vec3 dir=vec3(direction.x,direction.y,direction.z); - vec3 up=vec3(upDir.x,upDir.y,upDir.z); - vec3 p=type==DIRECTIONAL?vec3(pos.x,pos.y,pos.z)-.5f*farPlane*dir:vec3(position.x,position.y,position.z); - view=lookAt(p,p+dir,up); - proj=ortho(-10.f,10.f,-10.f,10.f,nearPlane,farPlane); - depthMapShader->use(); - depthMapShader->setMat4(proj*view,"lightMat"); - - mat4 model=translate(mat4(1.f),vec3(pos.x,pos.y,pos.z)); - model=rotate(model,rot.getAngle(),vec3(rotAxis.x,rotAxis.y,rotAxis.z)); + depthMapShader->setBool(type==POINT,"point"); depthMapShader->setMat4(model,"model"); + + if(type==POINT){ + depthMapShader->setFloat(farPlane,"farPlane"); + depthMapShader->setVec3(position,"lightPos"); + for(int j=0;j<6;j++) + depthMapShader->setMat4(proj*lookAt(p,p+dirs[j],1setMat4(proj*view,"lightMat"); + } mesh->render(); - - glBindFramebuffer(GL_FRAMEBUFFER,*(root->getFBO())); - glViewport(0,0,root->getWidth(),root->getHeight()); - - /* - for(Material *m : materials){ - Shader *shader=m->getShader(); - shader->use(); - shader->setInt(1+2*thisId+i,"light["+to_string(thisId)+"].depthMap["+to_string(i)+"]"); - depthMap->select(1+2*thisId+i); - } - */ - } - for(Material *m : materials){ - Shader *shader=m->getShader(); - shader->use(); - shader->setInt((int)type,"light["+to_string(thisId)+"].type"); - shader->setVec3(color,"light["+to_string(thisId)+"].color"); - shader->setInt(0,"tex"); - shader->setInt(1,"light["+to_string(thisId)+"].depthMap["+to_string(0)+"]"); - depthMap->select(1); - - switch(type){ - case POINT: - shader->setVec3(position,"light["+to_string(thisId)+"].pos"); - shader->setFloat(attenuationValues.x,"light["+to_string(thisId)+"].a"); - shader->setFloat(attenuationValues.y,"light["+to_string(thisId)+"].b"); - shader->setFloat(attenuationValues.z,"light["+to_string(thisId)+"].c"); - break; - case DIRECTIONAL: - shader->setMat4(proj*view,"light["+to_string(thisId)+"].lightMat"); - shader->setVec3(direction,"light["+to_string(thisId)+"].direction"); - break; - case SPOT: - shader->setMat4(proj*view,"light["+to_string(thisId)+"].lightMat"); - shader->setVec3(position,"light["+to_string(thisId)+"].pos"); - shader->setVec3(direction,"light["+to_string(thisId)+"].direction"); - shader->setFloat(attenuationValues.x,"light["+to_string(thisId)+"].a"); - shader->setFloat(attenuationValues.y,"light["+to_string(thisId)+"].b"); - shader->setFloat(attenuationValues.z,"light["+to_string(thisId)+"].c"); - shader->setFloat(innerAngle,"light["+to_string(thisId)+"].innerAngle"); - shader->setFloat(outerAngle,"light["+to_string(thisId)+"].outerAngle"); - break; - } } } } } + glBindFramebuffer(GL_FRAMEBUFFER,*(root->getFBO())); + glViewport(0,0,root->getWidth(),root->getHeight()); + for(Material *m : materials){ + Shader *shader=m->getShader(); + shader->use(); + shader->setInt((int)type,"light["+to_string(thisId)+"].type"); + shader->setVec3(color,"light["+to_string(thisId)+"].color"); + shader->setFloat(nearPlane,"light["+to_string(thisId)+"].near"); + shader->setFloat(farPlane,"light["+to_string(thisId)+"].far"); + shader->setInt(0,"tex"); + if(type==POINT) + shader->setInt(1,"light["+to_string(thisId)+"].depthMapCube"); + else + shader->setInt(1,"light["+to_string(thisId)+"].depthMap"); + depthMap->select(1); + /* + */ + + switch(type){ + case POINT: + shader->setVec3(position,"light["+to_string(thisId)+"].pos"); + shader->setFloat(attenuationValues.x,"light["+to_string(thisId)+"].a"); + shader->setFloat(attenuationValues.y,"light["+to_string(thisId)+"].b"); + shader->setFloat(attenuationValues.z,"light["+to_string(thisId)+"].c"); + break; + case DIRECTIONAL: + shader->setMat4(proj*view,"light["+to_string(thisId)+"].lightMat"); + shader->setVec3(direction,"light["+to_string(thisId)+"].direction"); + break; + case SPOT: + shader->setMat4(proj*view,"light["+to_string(thisId)+"].lightMat"); + shader->setVec3(position,"light["+to_string(thisId)+"].pos"); + shader->setVec3(direction,"light["+to_string(thisId)+"].direction"); + shader->setFloat(attenuationValues.x,"light["+to_string(thisId)+"].a"); + shader->setFloat(attenuationValues.y,"light["+to_string(thisId)+"].b"); + shader->setFloat(attenuationValues.z,"light["+to_string(thisId)+"].c"); + shader->setFloat(innerAngle,"light["+to_string(thisId)+"].innerAngle"); + shader->setFloat(outerAngle,"light["+to_string(thisId)+"].outerAngle"); + break; + } + } } } diff --git a/light.h b/light.h index 011fc32..fcab8a4 100755 --- a/light.h +++ b/light.h @@ -12,7 +12,7 @@ namespace vb01{ public: enum Type{POINT,DIRECTIONAL,SPOT,AMBIENT}; - Light(); + Light(Type); ~Light(); void update(); inline void setNode(Node *node){this->node=node;} @@ -24,7 +24,6 @@ namespace vb01{ attenuationValues.y=b; attenuationValues.z=c; } - inline void setType(Type t){this->type=t;} inline void setInnerAngle(float innerAngle){this->innerAngle=innerAngle;} inline void setOuterAngle(float outerAngle){this->outerAngle=outerAngle;} inline void setShadowNearPlane(float nearPlane){this->nearPlane=nearPlane;} diff --git a/node.cpp b/node.cpp index 03afe69..fd7b626 100755 --- a/node.cpp +++ b/node.cpp @@ -87,21 +87,20 @@ namespace vb01{ void Node::addLight(Light *light){ lights.push_back(light); light->setNode(this); + Root *root=Root::getSingleton(); Node *rootNode=Root::getSingleton()->getRootNode(); vector descendants; rootNode->getDescendants(rootNode,descendants); descendants.push_back(rootNode); - int numLights=0; - for(Node *n : descendants) - numLights+=n->getNumLights(); + root->numLights++; for(Node *n : descendants){ vector meshes=n->getMeshes(); for(Mesh *m : meshes){ Material *mat=m->getMaterial(); - string str=to_string(numLights>0?numLights:1); + string str=to_string(root->numLights>0?root->numLights:1); if(mat){ - mat->getShader()->editShader(true,'=',';',str); + //mat->getShader()->editShader(true,'=',';',str); mat->getShader()->editShader(false,'=',';',str); } } diff --git a/root.h b/root.h index da2d254..844a0cf 100755 --- a/root.h +++ b/root.h @@ -29,6 +29,7 @@ namespace vb01{ inline GLFWwindow* getWindow(){return window;} void createSkybox(std::string[6]); static Root* getSingleton(); + int numLights=0; private: Box *skybox=nullptr; Quad *guiPlane=nullptr; diff --git a/shader.cpp b/shader.cpp index 115d92e..769e18f 100755 --- a/shader.cpp +++ b/shader.cpp @@ -11,19 +11,25 @@ using namespace std; using namespace glm; namespace vb01{ - Shader::Shader(string vertShaderPath, string fragShaderPath){ - ifstream vertShaderFile,fragShaderFile; + Shader::Shader(string vertShaderPath, string fragShaderPath, string geoShaderPath){ + geometry=(geoShaderPath!=""); + + ifstream vertShaderFile,geoShaderFile,fragShaderFile; vertShaderFile.open(vertShaderPath); + geoShaderFile.open(geoShaderPath); fragShaderFile.open(fragShaderPath); - stringstream vertShaderStream,fragShaderStream; + stringstream vertShaderStream,geoShaderStream,fragShaderStream; vertShaderStream<glyph->bitmap.width, - face->glyph->bitmap.rows, - 0, - GL_RED, - GL_UNSIGNED_BYTE, - face->glyph->bitmap.buffer - ); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - glBindTexture(GL_TEXTURE_2D,0); - } - Texture::Texture(string path,bool flip){ bool png=false; int length=path.length(); @@ -104,6 +83,45 @@ namespace vb01{ } + Texture::Texture(int width){ + this->width=width; + this->type=TextureType::TEXTURE_CUBEMAP; + + glGenTextures(1,&texture); + glBindTexture(GL_TEXTURE_CUBE_MAP,texture); + + for(int i=0;i<6;i++) + glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i,0,GL_DEPTH_COMPONENT,width,width,0,GL_DEPTH_COMPONENT,GL_FLOAT,NULL); + + glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_CUBE_MAP,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); + + } + + Texture::Texture(FT_Face &face, char ch){ + glGenTextures(1,&texture); + glBindTexture(GL_TEXTURE_2D,texture); + glTexImage2D( + GL_TEXTURE_2D, + 0, + GL_RED, + face->glyph->bitmap.width, + face->glyph->bitmap.rows, + 0, + GL_RED, + GL_UNSIGNED_BYTE, + face->glyph->bitmap.buffer + ); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glBindTexture(GL_TEXTURE_2D,0); + } + Texture::~Texture(){ glBindTexture(type==TEXTURE_2D?GL_TEXTURE_2D:GL_TEXTURE_CUBE_MAP,0); glDeleteTextures(1,&texture); diff --git a/texture.frag b/texture.frag index cf6d20a..7bfea3f 100755 --- a/texture.frag +++ b/texture.frag @@ -1,7 +1,5 @@ #version 330 core - const int numLights=1; -const int numShadows=1; in vec3 fragPos; in vec3 norm; @@ -16,8 +14,9 @@ struct Light{ int type; vec3 pos,color,direction; float innerAngle,outerAngle; - float a,b,c; - sampler2D depthMap[numShadows]; + float a,b,c,near,far; + sampler2D depthMap; + samplerCube depthMapCube; mat4 lightMat; }; @@ -29,22 +28,46 @@ uniform bool castShadow; uniform vec4 diffuseColor; uniform vec3 camPos; -float getShadow(int id,int shadowId){ - vec3 projCoords=(light[id].lightMat*vec4(fragPos,1)).xyz/(light[id].lightMat*vec4(fragPos,1)).w; - projCoords=projCoords*.5+.5; - float closestDepth=texture(light[id].depthMap[shadowId],projCoords.xy).r; - float currentDepth=projCoords.z; - float bias=.005; - return currentDepth-bias>closestDepth?.7:0; +float linDepth(float depth,int i){ + float z=depth*2-1,near=light[i].near,far=light[i].far; + return (2*near*far)/(far+near-z*(far-near)); +} + +float getShadow(int id){ + int type=light[id].type; + + float shadow=0,closestDepth=0,currentDepth=0,bias=.005,val=.7; + if(type==0){ + vec3 projDir=fragPos-light[id].pos; + closestDepth=texture(light[id].depthMapCube,projDir).r*light[id].far; + currentDepth=length(projDir); + shadow=(currentDepth-bias>closestDepth)?val:0; + } + else{ + vec3 projCoords=(light[id].lightMat*vec4(fragPos,1)).xyz/(light[id].lightMat*vec4(fragPos,1)).w; + projCoords=projCoords*.5+.5; + closestDepth=texture(light[id].depthMap,projCoords.xy).r; + currentDepth=projCoords.z; + if(type==2){ + closestDepth=linDepth(closestDepth,id); + currentDepth=linDepth(currentDepth,id); + } + shadow=(currentDepth-bias>closestDepth)?val:0; + if(projCoords.z>1) + shadow=0; + } + return shadow; +/* +*/ } void main(){ vec4 finalColor=texturingEnabled?texture(tex,texCoords):diffuseColor; if(lightingEnabled){ - vec3 diffuseColor=vec3(0),specularColor; + vec3 diffuseColor=vec3(0),specularColor=vec3(0); float coef=1; for(int i=0;i #include +#include"util.h" #include FT_FREETYPE_H namespace vb01{ @@ -12,18 +13,20 @@ namespace vb01{ ~Texture(); Texture(int,int,bool=true); - Texture(FT_Face&,char); Texture(std::string,bool=false); Texture(std::string[6],bool=false); + Texture(int); + Texture(FT_Face&,char); void select(int=0); inline unsigned int* getTexture(){return &texture;} inline std::string getPath(){return path;} private: TextureType type=TextureType::TEXTURE_2D; - unsigned int texture; + u32 texture; + s64 lastUpdateTime=0; int width,height,numChannels; float weight; - unsigned char *data; + u8 *data; std::string path="",paths[6]; }; } diff --git a/texture.vert b/texture.vert index 581752c..ad37be9 100755 --- a/texture.vert +++ b/texture.vert @@ -1,7 +1,5 @@ #version 330 core -const int numLights=1; - layout (location=0) in vec3 aPos; layout (location=1) in vec3 aNorm; layout (location=2) in vec2 aTexCoords;