mirror of
https://github.com/devZoGok/vb01.git
synced 2026-08-26 19:43:30 +00:00
first iteration of the PBR shader
some bugfixes
This commit is contained in:
@@ -94,4 +94,7 @@ if(BUILD_SAMPLES)
|
||||
|
||||
add_executable(shadowSample shadowSample.cpp)
|
||||
target_link_libraries(shadowSample ${LIB_NAME})
|
||||
|
||||
add_executable(pbrSample pbrSample.cpp)
|
||||
target_link_libraries(pbrSample ${LIB_NAME})
|
||||
endif()
|
||||
|
||||
@@ -181,36 +181,36 @@ namespace vb01{
|
||||
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((int)type, "lights[" + to_string(thisId) + "].type");
|
||||
shader->setVec3(color, "lights[" + to_string(thisId) + "].color");
|
||||
shader->setFloat(nearPlane, "lights[" + to_string(thisId) + "].near");
|
||||
shader->setFloat(farPlane, "lights[" + to_string(thisId) + "].far");
|
||||
|
||||
int depthMapId = 10;
|
||||
shader->setInt(depthMapId, "light[" + to_string(thisId) + "].depthMap");
|
||||
shader->setInt(depthMapId + 1, "light[" + to_string(thisId) + "].depthMapCube");
|
||||
shader->setInt(depthMapId, "lights[" + to_string(thisId) + "].depthMap");
|
||||
shader->setInt(depthMapId + 1, "lights[" + to_string(thisId) + "].depthMapCube");
|
||||
depthMap->select(depthMapId + (type == POINT ? 1 : 0));
|
||||
|
||||
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");
|
||||
shader->setVec3(position, "lights[" + to_string(thisId) + "].pos");
|
||||
shader->setFloat(attenuationValues.x, "lights[" + to_string(thisId) + "].a");
|
||||
shader->setFloat(attenuationValues.y, "lights[" + to_string(thisId) + "].b");
|
||||
shader->setFloat(attenuationValues.z, "lights[" + to_string(thisId) + "].c");
|
||||
break;
|
||||
case DIRECTIONAL:
|
||||
shader->setMat4(proj * view, "light[" + to_string(thisId) + "].lightMat");
|
||||
shader->setVec3(direction, "light[" + to_string(thisId) + "].direction");
|
||||
shader->setMat4(proj * view, "lights[" + to_string(thisId) + "].lightMat");
|
||||
shader->setVec3(direction, "lights[" + 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");
|
||||
shader->setMat4(proj * view, "lights[" + to_string(thisId) + "].lightMat");
|
||||
shader->setVec3(position, "lights[" + to_string(thisId) + "].pos");
|
||||
shader->setVec3(direction,"lights[" + to_string(thisId) + "].direction");
|
||||
shader->setFloat(attenuationValues.x, "lights["+to_string(thisId) + "].a");
|
||||
shader->setFloat(attenuationValues.y, "lights["+to_string(thisId) + "].b");
|
||||
shader->setFloat(attenuationValues.z, "lights["+to_string(thisId) + "].c");
|
||||
shader->setFloat(innerAngle, "lights[" + to_string(thisId) + "].innerAngle");
|
||||
shader->setFloat(outerAngle, "lights[" + to_string(thisId) + "].outerAngle");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace vb01{
|
||||
Shader *depthMapShader;
|
||||
Texture *depthMap = nullptr;
|
||||
Node *node = nullptr;
|
||||
Vector3 color, attenuationValues = Vector3(1.8, .7, 1);
|
||||
Vector3 color = Vector3::VEC_IJK, attenuationValues = Vector3(1.8, .7, 1);
|
||||
float innerAngle = .707, outerAngle = .714, nearPlane = .1, farPlane = 100;
|
||||
unsigned int depthmapFBO, depthMapSize = 1024;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
#version 330 core
|
||||
const int numLights=1;
|
||||
const float PI = 3.14159;
|
||||
|
||||
in vec3 fragPos;
|
||||
in vec3 tan;
|
||||
in vec3 biTan;
|
||||
in vec3 norm;
|
||||
in vec2 texCoords;
|
||||
|
||||
layout (location = 0) out vec4 FragColor;
|
||||
layout (location = 1) out vec4 BrightColor;
|
||||
|
||||
//0-POINT,1-DIRECTIONAL,2-SPOT
|
||||
|
||||
struct Light{
|
||||
int type;
|
||||
vec3 pos, color, direction;
|
||||
float innerAngle, outerAngle;
|
||||
float a, b, c, near, far;
|
||||
sampler2D depthMap;
|
||||
samplerCube depthMapCube;
|
||||
mat4 lightMat;
|
||||
};
|
||||
|
||||
struct Texture{
|
||||
float mixRatio;
|
||||
sampler2D pastTexture, nextTexture;
|
||||
bool animated;
|
||||
};
|
||||
|
||||
uniform Light lights[numLights];
|
||||
uniform Texture textures[1];
|
||||
|
||||
uniform bool albedoMapEnabled;
|
||||
uniform vec4 albedoColor;
|
||||
uniform float roughness;
|
||||
uniform float metalness;
|
||||
uniform vec3 baseReflectivity;
|
||||
uniform vec3 camPos;
|
||||
|
||||
float trowbridgeReitz(vec3 n, vec3 h, float a){
|
||||
return a * a / (PI * pow(pow(max(dot(n, h), 0), 2) * (a * a - 1) + 1, 2));
|
||||
}
|
||||
|
||||
float schlickGGX(vec3 vec1, vec3 vec2, float k){
|
||||
float dotProd = max(dot(vec1, vec2), 0);
|
||||
return dotProd / (dotProd * (1 - k) + k);
|
||||
}
|
||||
|
||||
float geoSmith(vec3 n, vec3 v, vec3 l, float k){
|
||||
float ggx1 = schlickGGX(n, v, k);
|
||||
float ggx2 = schlickGGX(n, l, k);
|
||||
return ggx1 * ggx2;
|
||||
}
|
||||
|
||||
vec3 fresnelSchlick(vec3 v, vec3 h, vec3 f0){
|
||||
return f0 + (vec3(1) - f0) * pow(1 - max(dot(v, h), 0), 5);
|
||||
}
|
||||
|
||||
vec3 lambertDiffuse(vec4 color){
|
||||
return (color / PI).xyz;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 finalColor = vec4(0, 0, 0, 1);
|
||||
vec3 normal = norm;
|
||||
vec3 viewDir = normalize(camPos - fragPos);
|
||||
vec4 albedo = (albedoMapEnabled ? texture(textures[0].pastTexture, texCoords) : albedoColor);
|
||||
|
||||
for(int i = 0; i < numLights; ++i){
|
||||
vec3 lightDir;
|
||||
float dist = length(lights[i].pos - fragPos), attenuation = 1, a = lights[i].a, b = lights[i].b, c = lights[i].c;
|
||||
|
||||
if(lights[i].type == 0){
|
||||
lightDir = normalize(lights[i].pos - fragPos);
|
||||
attenuation = 1 / (a * dist * dist + b * dist + c);
|
||||
}
|
||||
else if(lights[i].type == 1){
|
||||
lightDir = -normalize(lights[i].direction);
|
||||
}
|
||||
else if(lights[i].type == 2){
|
||||
lightDir = normalize(lights[i].pos - fragPos);
|
||||
attenuation = 1 / (a * dist * dist + b * dist + c);
|
||||
}
|
||||
|
||||
vec3 halfVec = normalize(lightDir + normal);
|
||||
|
||||
float D = trowbridgeReitz(normal, halfVec, roughness * roughness);
|
||||
float G = geoSmith(normal, halfVec, lightDir, 0.5 * roughness * roughness);
|
||||
vec3 F = fresnelSchlick(viewDir, halfVec, baseReflectivity);
|
||||
vec3 cookTor = D * G * F / max(4 * max(dot(viewDir, normal), 0) * max(dot(lightDir, normal), 0), .000001);
|
||||
|
||||
vec3 fDiff = lambertDiffuse(albedo);
|
||||
vec3 kDiff = (vec3(1) - F) * (1 - metalness);
|
||||
|
||||
finalColor.rgb += (kDiff * fDiff + cookTor) * lights[i].color * attenuation * max(dot(lightDir, normal), 0);
|
||||
}
|
||||
|
||||
float brightness = dot(finalColor.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
|
||||
if(brightness > 1)
|
||||
BrightColor = vec4(finalColor.rgb, 1);
|
||||
|
||||
FragColor = finalColor;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#version 330 core
|
||||
|
||||
const int numBones = 1;
|
||||
const int numVertGroups = 1;
|
||||
const int numMaxInfluences = 4;
|
||||
const int numShapeKeys = 1;
|
||||
|
||||
layout (location = 0) in vec3 aPos;
|
||||
layout (location = 1) in vec3 aNorm;
|
||||
layout (location = 2) in vec2 aTexCoords;
|
||||
layout (location = 3) in vec3 aTan;
|
||||
layout (location = 4) in vec3 aBiTan;
|
||||
|
||||
out vec3 fragPos, norm, tan, biTan;
|
||||
out vec2 texCoords;
|
||||
|
||||
struct Bone{
|
||||
float angle;
|
||||
vec3 pos, trans, rotAxis, scale;
|
||||
int vertGroup, parent;
|
||||
};
|
||||
|
||||
uniform bool animated;
|
||||
uniform Bone bones[numBones];
|
||||
uniform mat4 model;
|
||||
uniform mat4 view;
|
||||
uniform mat4 proj;
|
||||
uniform float[numShapeKeys] shapeKeyFactors;
|
||||
|
||||
void main(){
|
||||
mat3 normalMat = mat3(transpose(inverse(model)));
|
||||
norm = (normalMat * aNorm);
|
||||
tan = (normalMat * aTan);
|
||||
biTan = (normalMat * aBiTan);
|
||||
fragPos = vec3(model * vec4(aPos, 1));
|
||||
texCoords = aTexCoords;
|
||||
|
||||
gl_Position = proj * view * model * vec4(aPos, 1);
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#include "root.h"
|
||||
#include "model.h"
|
||||
#include "material.h"
|
||||
#include "texture.h"
|
||||
#include "light.h"
|
||||
#include "box.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
using namespace vb01;
|
||||
using namespace std;
|
||||
|
||||
int main() {
|
||||
const string PATH = "../", TEX_PATH = PATH + "samples/textures/", MODEL_PATH = PATH + "samples/models/";
|
||||
string skyboxTextures[] = {
|
||||
TEX_PATH + "top.jpg",
|
||||
TEX_PATH + "bottom.jpg",
|
||||
TEX_PATH + "left.jpg",
|
||||
TEX_PATH + "right.jpg",
|
||||
TEX_PATH + "front.jpg",
|
||||
TEX_PATH + "back.jpg"
|
||||
};
|
||||
|
||||
/*
|
||||
* Gets Root object to start the sample,
|
||||
* also passes the base path for asset retrieval.
|
||||
*/
|
||||
Root *root = Root::getSingleton();
|
||||
root->start(800, 600, PATH, "Light sample");
|
||||
root->createSkybox(skyboxTextures);
|
||||
root->setHDREnabled(true);
|
||||
|
||||
Camera *cam = root->getCamera();
|
||||
cam->setPosition(Vector3(1, 1, 1) * 5);
|
||||
cam->lookAt(Vector3(-1, -1, -1).norm(), Vector3(-1, 1, -1).norm());
|
||||
|
||||
Node *rootNode = root->getRootNode();
|
||||
|
||||
Model *model = new Model(MODEL_PATH + "teapot.vb");
|
||||
Material *mat = new Material(PATH + "pbr");
|
||||
mat->addBoolUniform("albedoMapEnabled", false);
|
||||
mat->addVec4Uniform("albedoColor", Vector4(1, 1, 1, 1));
|
||||
mat->addFloatUniform("roughness", .1);
|
||||
mat->addFloatUniform("metalness", .1);
|
||||
mat->addVec3Uniform("baseReflectivity", Vector3(0.563, 0.579, 0.579));
|
||||
/*
|
||||
mat = new Material(PATH + "texture");
|
||||
mat->addBoolUniform("texturingEnabled", true);
|
||||
mat->addBoolUniform("lightingEnabled", true);
|
||||
string fr[]{TEX_PATH + "bricks.jpg"};
|
||||
mat->addTexUniform("textures[0]", new Texture(fr, 1), true);
|
||||
*/
|
||||
model->setMaterial(mat);
|
||||
rootNode->attachChild(model);
|
||||
|
||||
{
|
||||
Light *light = new Light(Light::POINT);
|
||||
light->setAttenuationValues(.00001, .00001, 1);
|
||||
light->setColor(Vector3(1, 0, 0));
|
||||
light->setInnerAngle(.1);
|
||||
light->setOuterAngle(.1);
|
||||
Node *lightNode = new Node();
|
||||
Box *b = new Box(Vector3(1, 1, 1) * .1);
|
||||
Material *m = new Material(PATH + "texture");
|
||||
m->addBoolUniform("texturingEnabled", false);
|
||||
m->addBoolUniform("lightingEnabled", false);
|
||||
m->addVec4Uniform("diffuseColor", Vector4(1, 0, 0, 1));
|
||||
b->setMaterial(m);
|
||||
lightNode->attachMesh(b);
|
||||
lightNode->addLight(light);
|
||||
rootNode->attachChild(lightNode);
|
||||
lightNode->setPosition(Vector3(2, 3, 0));
|
||||
lightNode->setOrientation(Quaternion(1.57, Vector3::VEC_I));
|
||||
}
|
||||
{
|
||||
Light *light = new Light(Light::POINT);
|
||||
light->setAttenuationValues(.00001, .00001, 1);
|
||||
light->setColor(Vector3(0, 0, 1));
|
||||
light->setInnerAngle(.1);
|
||||
light->setOuterAngle(.1);
|
||||
Node *lightNode = new Node();
|
||||
Box *b = new Box(Vector3(1, 1, 1) * .1);
|
||||
Material *m = new Material(PATH + "texture");
|
||||
m->addBoolUniform("texturingEnabled", false);
|
||||
m->addBoolUniform("lightingEnabled", false);
|
||||
m->addVec4Uniform("diffuseColor", Vector4(0, 0, 1, 1));
|
||||
b->setMaterial(m);
|
||||
lightNode->attachMesh(b);
|
||||
lightNode->addLight(light);
|
||||
rootNode->attachChild(lightNode);
|
||||
lightNode->setPosition(Vector3(-2, 3, 0));
|
||||
lightNode->setOrientation(Quaternion(1.57, Vector3::VEC_I));
|
||||
}
|
||||
|
||||
while(true)
|
||||
root->update();
|
||||
|
||||
return 0;
|
||||
}
|
||||
+24
-24
@@ -31,35 +31,34 @@ struct Texture{
|
||||
|
||||
uniform Texture textures[4];
|
||||
uniform samplerCube environmentMap;
|
||||
uniform Light light[numLights];
|
||||
uniform Light lights[numLights];
|
||||
uniform bool lightingEnabled, texturingEnabled, normalMapEnabled, specularMapEnabled, castShadow, environmentMapEnabled;
|
||||
uniform vec4 diffuseColor, specularColor;
|
||||
uniform float shinyness, specularStrength;
|
||||
uniform vec3 camPos;
|
||||
|
||||
float linDepth(float depth, int i){
|
||||
float z = depth * 2 - 1, near = light[i].near, far = light[i].far;
|
||||
float z = depth * 2 - 1, near = lights[i].near, far = lights[i].far;
|
||||
return (2 * near * far) / (far + near - z * (far - near));
|
||||
}
|
||||
|
||||
float getShadow(int id){
|
||||
int type = light[id].type;
|
||||
int type = lights[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;
|
||||
vec3 projDir = fragPos - lights[id].pos;
|
||||
closestDepth = texture(lights[id].depthMapCube, projDir).r * lights[id].far;
|
||||
currentDepth = length(projDir);
|
||||
shadow = (currentDepth - bias > closestDepth) ? val : 0;
|
||||
}
|
||||
else{
|
||||
vec4 lightSpaceFragPos = light[id].lightMat * vec4(fragPos, 1);
|
||||
vec4 lightSpaceFragPos = lights[id].lightMat * vec4(fragPos, 1);
|
||||
vec3 projCoords = (lightSpaceFragPos.xyz / lightSpaceFragPos.w) * .5 + .5;
|
||||
closestDepth = texture(light[id].depthMap, projCoords.xy).r;
|
||||
closestDepth = texture(lights[id].depthMap, projCoords.xy).r;
|
||||
currentDepth = projCoords.z;
|
||||
if(type == 2){
|
||||
closestDepth = linDepth(closestDepth, id);
|
||||
currentDepth = linDepth(currentDepth, id);
|
||||
closestDepth = linDepth(closestDepth, id); currentDepth = linDepth(currentDepth, id);
|
||||
}
|
||||
shadow = (currentDepth - bias > closestDepth) ? val : 0;
|
||||
if(projCoords.z > 1)
|
||||
@@ -68,7 +67,8 @@ float getShadow(int id){
|
||||
return shadow;
|
||||
}
|
||||
|
||||
void main(){ vec4 finalColor = diffuseColor;
|
||||
void main(){
|
||||
vec4 finalColor = diffuseColor;
|
||||
|
||||
if(texturingEnabled){
|
||||
vec4 textureColor = texture(textures[0].pastTexture, texCoords);
|
||||
@@ -93,36 +93,36 @@ void main(){ vec4 finalColor = diffuseColor;
|
||||
for(int i = 0; i < numLights; i++){
|
||||
vec3 lightDir = vec3(0), viewDir = normalize(camPos - fragPos);
|
||||
float attenuation = 1.0;
|
||||
float a = light[i].a, b = light[i].b, c = light[i].c, dist = length(fragPos - light[i].pos), factor, coef = 1;
|
||||
float a = lights[i].a, b = lights[i].b, c = lights[i].c, dist = length(fragPos - lights[i].pos), factor, coef = 1;
|
||||
|
||||
if(light[i].type == 0){
|
||||
lightDir = normalize(light[i].pos - fragPos);
|
||||
if(lights[i].type == 0){
|
||||
lightDir = normalize(lights[i].pos - fragPos);
|
||||
attenuation = 1.0 / (a * dist * dist + b * dist + c);
|
||||
}
|
||||
else if(light[i].type == 1){
|
||||
lightDir = -normalize(light[i].direction);
|
||||
else if(lights[i].type == 1){
|
||||
lightDir = -normalize(lights[i].direction);
|
||||
}
|
||||
else if(light[i].type == 2){
|
||||
lightDir = normalize(light[i].pos - fragPos);
|
||||
float innerAngle = light[i].innerAngle;
|
||||
float angle = acos(dot(-lightDir, light[i].direction));
|
||||
float outerAngle = light[i].outerAngle;
|
||||
if(light[i].innerAngle <= angle && angle <= light[i].outerAngle){
|
||||
else if(lights[i].type == 2){
|
||||
lightDir = normalize(lights[i].pos - fragPos);
|
||||
float innerAngle = lights[i].innerAngle;
|
||||
float angle = acos(dot(-lightDir, lights[i].direction));
|
||||
float outerAngle = lights[i].outerAngle;
|
||||
if(lights[i].innerAngle <= angle && angle <= lights[i].outerAngle){
|
||||
coef = (angle - outerAngle) / (innerAngle - outerAngle);
|
||||
}
|
||||
if(angle > light[i].outerAngle){
|
||||
if(angle > lights[i].outerAngle){
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
factor = max(dot(lightDir, normal), 0.);
|
||||
diffuseCol += light[i].color * (factor * attenuation * coef);
|
||||
diffuseCol += lights[i].color * (factor * attenuation * coef);
|
||||
|
||||
if(specularMapEnabled){
|
||||
float specularSample = texture(textures[2].pastTexture, texCoords).r;
|
||||
vec3 halfwayVec = normalize(lightDir + viewDir);
|
||||
float spec = pow(max(dot(normal, halfwayVec), 0), shinyness);
|
||||
specularCol += specularStrength * spec * specularSample * light[i].color;
|
||||
specularCol += specularStrength * spec * specularSample * lights[i].color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user