396 lines
No EOL
12 KiB
C++
396 lines
No EOL
12 KiB
C++
#include "rendering.hpp"
|
|
#include "camera.hpp"
|
|
#include "light.hpp"
|
|
#include "multipass.hpp"
|
|
#include "shader.hpp"
|
|
#include <glm/ext/matrix_float4x4.hpp>
|
|
#include <glm/ext/matrix_transform.hpp>
|
|
#include <iostream>
|
|
#include <vector>
|
|
|
|
bool rendering::SDLinit() {
|
|
// init
|
|
SDL_Init(SDL_INIT_VIDEO);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
|
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
|
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
|
|
return true;
|
|
}
|
|
|
|
bool rendering::GLinit(SDL_Window *window) {
|
|
this->context = SDL_GL_CreateContext(window);
|
|
|
|
glewExperimental = GL_TRUE;
|
|
glewInit();
|
|
return true;
|
|
}
|
|
|
|
bool rendering::Shaderinit() {
|
|
// read manifest
|
|
std::ifstream shader_manifest("shaders.json", std::ifstream::binary);
|
|
Json::Value manifest;
|
|
shader_manifest >> manifest;
|
|
|
|
// ====get vertex====
|
|
|
|
if (!manifest["vertex"].isArray()) {
|
|
std::cerr << "Malformed shader.json (vertex)";
|
|
return false;
|
|
}
|
|
|
|
std::vector<std::string> shaderpaths_vertex;
|
|
|
|
// --get paths--
|
|
for (int i = 0; i < manifest["vertex"].size(); i++) {
|
|
shaderpaths_vertex.push_back(manifest["vertex"][i]["path"].asString());
|
|
}
|
|
|
|
std::vector<std::string> shadercode_vertex;
|
|
|
|
// --read paths--
|
|
|
|
for (int i = 0; i < shaderpaths_vertex.size(); i++) {
|
|
std::ifstream vert(shaderpaths_vertex.at(i));
|
|
if (vert.is_open()) {
|
|
std::ostringstream ss;
|
|
ss << vert.rdbuf();
|
|
shadercode_vertex.push_back(ss.str());
|
|
} else {
|
|
std::cerr << "vertex shader: " << shaderpaths_vertex.at(i)
|
|
<< " is missing.\n";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// --compile vertex--
|
|
|
|
for (int i = 0; i < shadercode_vertex.size(); i++) {
|
|
this->vertex_shaders.push_back(glCreateShader(GL_VERTEX_SHADER));
|
|
const char *code = shadercode_vertex.at(i).c_str();
|
|
glShaderSource(this->vertex_shaders.back(), 1, &code, NULL);
|
|
glCompileShader(this->vertex_shaders.back());
|
|
GLint status;
|
|
glGetShaderiv(this->vertex_shaders.back(), GL_COMPILE_STATUS, &status);
|
|
if (status != GL_TRUE) {
|
|
char buffer[512];
|
|
glGetShaderInfoLog(this->vertex_shaders.back(), 512, NULL, buffer);
|
|
std::cerr << "shader compilation error on shader: "
|
|
<< shaderpaths_vertex.at(i) << "\n"
|
|
<< buffer << "\n";
|
|
}
|
|
}
|
|
|
|
|
|
// ====get geometry====
|
|
|
|
if (!manifest["geometry"].isArray()) {
|
|
std::cerr << "Malformed shader.json (geometry)";
|
|
return false;
|
|
}
|
|
|
|
std::vector<std::string> shaderpaths_geometry;
|
|
|
|
// --get paths--
|
|
for (int i = 0; i < manifest["geometry"].size(); i++) {
|
|
shaderpaths_geometry.push_back(manifest["geometry"][i]["path"].asString());
|
|
}
|
|
|
|
std::vector<std::string> shadercode_geometry;
|
|
|
|
// --read paths--
|
|
|
|
for (int i = 0; i < shaderpaths_geometry.size(); i++) {
|
|
std::ifstream vert(shaderpaths_geometry.at(i));
|
|
if (vert.is_open()) {
|
|
std::ostringstream ss;
|
|
ss << vert.rdbuf();
|
|
shadercode_geometry.push_back(ss.str());
|
|
} else {
|
|
std::cerr << "geometry shader: " << shaderpaths_geometry.at(i)
|
|
<< " is missing.\n";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// --compile geometry--
|
|
|
|
for (int i = 0; i < shadercode_geometry.size(); i++) {
|
|
this->geometry_shaders.push_back(glCreateShader(GL_GEOMETRY_SHADER));
|
|
const char *code = shadercode_geometry.at(i).c_str();
|
|
glShaderSource(this->geometry_shaders.back(), 1, &code, NULL);
|
|
glCompileShader(this->geometry_shaders.back());
|
|
GLint status;
|
|
glGetShaderiv(this->geometry_shaders.back(), GL_COMPILE_STATUS, &status);
|
|
if (status != GL_TRUE) {
|
|
char buffer[512];
|
|
glGetShaderInfoLog(this->geometry_shaders.back(), 512, NULL, buffer);
|
|
std::cerr << "shader compilation error on shader: "
|
|
<< shaderpaths_geometry.at(i) << "\n"
|
|
<< buffer << "\n";
|
|
}
|
|
}
|
|
|
|
// ====get fragment====
|
|
|
|
if (!manifest["fragment"].isArray()) {
|
|
std::cerr << "Malformed shader.json (fragment)";
|
|
return false;
|
|
}
|
|
|
|
std::vector<std::string> shaderpaths_fragment;
|
|
|
|
// --get paths--
|
|
for (int i = 0; i < manifest["fragment"].size(); i++) {
|
|
shaderpaths_fragment.push_back(manifest["fragment"][i]["path"].asString());
|
|
}
|
|
|
|
std::vector<std::string> shadercode_fragment;
|
|
|
|
// --read paths--
|
|
|
|
for (int i = 0; i < shaderpaths_fragment.size(); i++) {
|
|
std::ifstream vert(shaderpaths_fragment.at(i));
|
|
if (vert.is_open()) {
|
|
std::ostringstream ss;
|
|
ss << vert.rdbuf();
|
|
shadercode_fragment.push_back(ss.str());
|
|
} else {
|
|
std::cerr << "fragment shader: " << shaderpaths_fragment.at(i)
|
|
<< " is missing.\n";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// --compile fragment--
|
|
|
|
for (int i = 0; i < shadercode_fragment.size(); i++) {
|
|
this->fragment_shaders.push_back(glCreateShader(GL_FRAGMENT_SHADER));
|
|
const char *code = shadercode_fragment.at(i).c_str();
|
|
glShaderSource(this->fragment_shaders.back(), 1, &code, NULL);
|
|
glCompileShader(this->fragment_shaders.back());
|
|
GLint status;
|
|
glGetShaderiv(this->fragment_shaders.back(), GL_COMPILE_STATUS, &status);
|
|
if (status != GL_TRUE) {
|
|
char buffer[512];
|
|
glGetShaderInfoLog(this->fragment_shaders.back(), 512, NULL, buffer);
|
|
std::cerr << "shader compilation error on shader: "
|
|
<< shaderpaths_fragment.at(i) << "\n"
|
|
<< buffer << "\n";
|
|
}
|
|
}
|
|
|
|
// linking it all together
|
|
|
|
if (!manifest["combos"].isArray()) {
|
|
std::cerr << "Malformed shader.json (combos)";
|
|
}
|
|
|
|
for (int i = 0; i < manifest["combos"].size(); i++) {
|
|
shader shader;
|
|
// vertex
|
|
if (manifest["combos"][i]["vertex"].isInt()) {
|
|
shader.vertexShader =
|
|
vertex_shaders.at(manifest["combos"][i]["vertex"].asInt());
|
|
} else {
|
|
std::cerr << "required argument \"vetex\" is nonexistant or not an int";
|
|
return false;
|
|
}
|
|
// fragment
|
|
if (manifest["combos"][i]["fragment"].isInt()) {
|
|
shader.fragmentShader =
|
|
fragment_shaders.at(manifest["combos"][i]["fragment"].asInt());
|
|
} else {
|
|
std::cerr
|
|
<< "required argument \"fragment\" is nonexistant or not an int\n";
|
|
return false;
|
|
}
|
|
|
|
if (manifest["combos"][i]["geometry"].isInt()) {
|
|
shader.geometryShader =
|
|
geometry_shaders.at(manifest["combos"][i]["geometry"].asInt());
|
|
shader.geoshd=true;
|
|
}
|
|
|
|
if (!manifest["fragment"][manifest["combos"][i]["fragment"].asInt()]
|
|
["framebuff_output"]
|
|
.isArray()) {
|
|
std::cerr << "vertex[" << i << "].framebuff_output is not an array.\n";
|
|
return false;
|
|
}
|
|
|
|
shader.attatchshader();
|
|
for (int j = 0;
|
|
j < manifest["fragment"][manifest["combos"][i]["fragment"].asInt()]
|
|
["framebuff_output"]
|
|
.size();
|
|
j++) {
|
|
glBindFragDataLocation(
|
|
shader.shaderProgram, j,
|
|
manifest["fragment"][manifest["combos"][i]["fragment"].asInt()]
|
|
["framebuff_output"][j]
|
|
.asCString());
|
|
}
|
|
|
|
shader.linkshader();
|
|
|
|
GLint success;
|
|
__glewGetProgramiv(shader.shaderProgram,GL_LINK_STATUS,&success);
|
|
std::cout<<"\n"<<i<<" status "<<success<<"\n",
|
|
|
|
this->shaders.push_back(shader);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void rendering::render(camera cam, shader *depthshd, shader *shadowcalc, Gbuffer *gbuf) {
|
|
|
|
//shadow Pass
|
|
|
|
for (int i=0; i<lights.size(); i++) {
|
|
light *clight=&lights.at(i);
|
|
|
|
//// DEPTH PASS ////
|
|
depthshd->use();
|
|
glCullFace(GL_FRONT);
|
|
for (int j=0; j<objects.size(); j++) {
|
|
objects.at(j).get().renderShadows(*clight, SHADOW_WIDTH, SHADOW_HEIGHT, depthCubemap, depthshd, depthFBO, farClipPlane, cam, (j==0));
|
|
}
|
|
glCullFace(GL_BACK);
|
|
|
|
//// SHADOW PASS ////
|
|
shadowcalc->use();
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap);
|
|
glUniform1i(shadowcalc->getUniformId("depthMap"), 0);
|
|
|
|
glActiveTexture(GL_TEXTURE1);
|
|
glBindTexture(GL_TEXTURE_2D, gbuf->textus[gbuf->GBUFER_TEXTURE_SHADOW]);
|
|
glUniform1i(shadowcalc->getUniformId("GbufPrevShadow"), 1);
|
|
|
|
glUniform3f(shadowcalc->getUniformId("lights[0].Position"), clight->position.x, clight->position.y, clight->position.z);
|
|
glUniform3f(shadowcalc->getUniformId("lights[0].Color"), 1.f,1.f,1.f);
|
|
glUniform1f(shadowcalc->getUniformId("far_plane"), farClipPlane);
|
|
|
|
gbuf->bindW();
|
|
gbuf->clearw();
|
|
|
|
for (int j=0; j<objects.size(); j++) {
|
|
objects.at(j).get().renderShadowCalc(cam, shadowcalc);
|
|
}
|
|
}
|
|
glClear(GL_DEPTH_BUFFER_BIT);
|
|
glClearDepth(1.0);
|
|
|
|
// gbuf->bindW();
|
|
// gbuf->clear();
|
|
for (int i = 0; i < objects.size(); i++) {
|
|
objects.at(i).get().rend_shader->use();
|
|
objects.at(i).get().render(cam);
|
|
}
|
|
|
|
shaders.at(2).use();
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
gbuf->bindR();
|
|
// tex 0 position
|
|
// tex 1 normals
|
|
// tex 2 diffuse (albedo)
|
|
// tex 3 texcoord
|
|
// tex 4 shadow
|
|
|
|
setupTextureDS(*gbuf);
|
|
|
|
glUniform1i(shaders.at(2).getUniformId("gPosition"),0);
|
|
glUniform1i(shaders.at(2).getUniformId("gNormal"),1);
|
|
glUniform1i(shaders.at(2).getUniformId("gAlbedoSpec"),2);
|
|
glUniform1i(shaders.at(2).getUniformId("gShadow"),4);
|
|
|
|
|
|
// for (int i =0; i<lights.size(); i++) {
|
|
|
|
// }
|
|
glUniform3f(shaders.at(2).getUniformId("lights[0].Position"), 0.f,0.f,0.f);
|
|
glUniform3f(shaders.at(2).getUniformId("lights[0].Color"), 1.f,1.f,1.f);
|
|
|
|
renderlighting(shaders.at(2).getInputId("position"),shaders.at(2).getInputId("TexCoord"));
|
|
|
|
}
|
|
|
|
void rendering::renderlighting(GLuint pos, GLuint txc) {
|
|
// shamelessly stolen from
|
|
// https://learnopengl.com/code_viewer_gh.php?code=src/5.advanced_lighting/8.1.deferred_shading/deferred_shading.cpp
|
|
// bc i'm lazy
|
|
if (quadVAO == 0) {
|
|
float quadVertices[] = {
|
|
// positions // texture Coords
|
|
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
|
1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
|
};
|
|
// setup plane VAO
|
|
glGenVertexArrays(1, &quadVAO);
|
|
glGenBuffers(1, &quadVBO);
|
|
glBindVertexArray(quadVAO);
|
|
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVertices), &quadVertices,
|
|
GL_STATIC_DRAW);
|
|
glEnableVertexAttribArray(pos);
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float),
|
|
(void *)0);
|
|
glEnableVertexAttribArray(txc);
|
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float),
|
|
(void *)(3 * sizeof(float)));
|
|
}
|
|
glBindVertexArray(quadVAO);
|
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
glBindVertexArray(0);
|
|
}
|
|
|
|
void rendering::setupTextureDS(Gbuffer gbuf){
|
|
for (int i = 0; i<12&&i<gbuf.GBUFER_NUM_TEXTURES; i++) {
|
|
glActiveTexture(GL_TEXTURE0+i);
|
|
glBindTexture(GL_TEXTURE_2D, gbuf.textus[i]);
|
|
}
|
|
}
|
|
|
|
void rendering::cpyDepthBuffer(GLuint buffer){
|
|
__glewBindFramebuffer(GL_READ_FRAMEBUFFER, buffer);
|
|
__glewBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
}
|
|
|
|
void rendering::mkDepthBuffer(){
|
|
glGenRenderbuffers(1, &rboDepth);
|
|
glBindRenderbuffer(GL_RENDERBUFFER, rboDepth);
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepth);
|
|
}
|
|
|
|
|
|
void rendering::mkShadowCubemap(){
|
|
glGenFramebuffers(1,&depthFBO);
|
|
glGenTextures(1, &depthCubemap);
|
|
glBindTexture(GL_TEXTURE_CUBE_MAP, depthCubemap);
|
|
for (unsigned int i = 0; i < 6; ++i)
|
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT,
|
|
SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
|
|
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_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);
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, depthFBO);
|
|
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depthCubemap, 0);
|
|
glDrawBuffer(GL_NONE);
|
|
glReadBuffer(GL_NONE);
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
|
|
|
|
} |