This commit is contained in:
lukas 2022-02-05 21:44:31 +01:00
commit a00022523f
27 changed files with 1178 additions and 0 deletions

34
CMakeLists.txt Normal file
View File

@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.21)
project(opengltest)
set(CMAKE_CXX_STANDARD 14)
# We need a CMAKE_DIR with some code to find external dependencies
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
# OpenGL
find_package(OpenGL REQUIRED)
# GLM
find_package(GLM REQUIRED)
message(STATUS "GLM included at ${GLM_INCLUDE_DIR}")
# GLFW
find_package(GLFW3 REQUIRED)
message(STATUS "Found GLFW3 in ${GLFW3_INCLUDE_DIR}")
SET(srcs main.cpp gl/Shader.cpp gl/Shader.h
gl/IndexBuffer.cpp gl/IndexBuffer.h
gl/VertexBuffer.cpp gl/VertexBuffer.h
gl/VertexArray.cpp gl/VertexArray.h
gl/Renderer.cpp gl/Renderer.h
blocks/BaseBlock.cpp blocks/BaseBlock.h
blocks/GrasBlock.cpp blocks/GrasBlock.h
blocks/BlockRenderer.cpp blocks/BlockRenderer.h
blocks/RenderBase.cpp blocks/RenderBase.h
gl/Camera.cpp gl/Camera.h)
add_executable(opengltest ${srcs})
target_link_libraries(opengltest ${GLFW3_LIBRARY} ${OPENGL_LIBRARY} )

27
blocks/BaseBlock.cpp Normal file
View File

@ -0,0 +1,27 @@
//
// Created by lukas on 04.02.22.
//
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <cstdlib>
#include <glm/ext/matrix_float4x4.hpp>
#include <glm/ext/matrix_transform.hpp>
#include "BaseBlock.h"
#include "BlockRenderer.h"
void BaseBlock::render() {
glUniform3f(BlockRenderer::getInstance()->getUniformhandle("u_color"), r, g, b);
glm::mat4 position = glm::translate(glm::mat4(1.0f), glm::vec3((float) xpos * 2, (float) ypos * 2, (float) zpos * 2));
glUniformMatrix4fv(BlockRenderer::getInstance()->getUniformhandle("translation"), 1, GL_FALSE, &position[0][0]);
BlockRenderer::getInstance()->render();
}
BaseBlock::BaseBlock(float r, float g, float b, uint xpos, uint ypos, uint zpos) : r(r), g(g), b(b), xpos(xpos), ypos(ypos), zpos(zpos) {
// BlockRenderer::init();
// this->getrenderer().init();
}

23
blocks/BaseBlock.h Normal file
View File

@ -0,0 +1,23 @@
//
// Created by lukas on 04.02.22.
//
#ifndef OPENGLTEST_BASEBLOCK_H
#define OPENGLTEST_BASEBLOCK_H
#include "BlockRenderer.h"
class BaseBlock {
private:
float r,g,b;
uint xpos,ypos,zpos;
public:
BaseBlock(float r, float g, float b, uint xpos, uint ypos, uint zpos);
void render();
};
#endif //OPENGLTEST_BASEBLOCK_H

89
blocks/BlockRenderer.cpp Normal file
View File

@ -0,0 +1,89 @@
//
// Created by lukas on 05.02.22.
//
#include "BlockRenderer.h"
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
VertexArray *BlockRenderer::setVertexArray() {
float cube_vertices[] = {
// front
-1.0, -1.0, 1.0,
1.0, -1.0, 1.0,
1.0, 1.0, 1.0,
-1.0, 1.0, 1.0,
// back
-1.0, -1.0, -1.0,
1.0, -1.0, -1.0,
1.0, 1.0, -1.0,
-1.0, 1.0, -1.0
};
GLfloat cube_colors[] = {
// front colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0,
// back colors
1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0,
1.0, 1.0, 1.0
};
// Generate a vertex buffer
auto *vb = new VertexBuffer(cube_vertices, sizeof(cube_vertices));
//
return new VertexArray(*vb);
}
IndexBuffer *BlockRenderer::setIndexBuffer() {
unsigned cube_elements[] = {
// front
0, 1, 2,
2, 3, 0,
// right
1, 5, 6,
6, 2, 1,
// back
7, 6, 5,
5, 4, 7,
// left
4, 0, 3,
3, 7, 4,
// bottom
4, 5, 1,
1, 0, 4,
// top
3, 2, 6,
6, 7, 3
};
return new IndexBuffer(cube_elements, 36);;
}
Shader BlockRenderer::setShader() {
const std::string vertsrc =
#include "vertex.shader"
const std::string geosrc =
#include "geometry.shader"
const std::string fragsrc =
#include "fragment.shader"
Shader s;
s.loadShader(vertsrc, geosrc, fragsrc);
s.Bind();
return s;
}
BlockRenderer::BlockRenderer() {}

26
blocks/BlockRenderer.h Normal file
View File

@ -0,0 +1,26 @@
//
// Created by lukas on 05.02.22.
//
#ifndef OPENGLTEST_BLOCKRENDERER_H
#define OPENGLTEST_BLOCKRENDERER_H
#include "../gl/Renderer.h"
#include "../gl/Shader.h"
#include "RenderBase.h"
#include <iostream>
class BlockRenderer : public RenderBase<BlockRenderer> {
public:
BlockRenderer();
VertexArray* setVertexArray() override;
Shader setShader() override;
IndexBuffer *setIndexBuffer() override;
};
#endif //OPENGLTEST_BLOCKRENDERER_H

8
blocks/GrasBlock.cpp Normal file
View File

@ -0,0 +1,8 @@
//
// Created by lukas on 04.02.22.
//
#include "GrasBlock.h"
GrasBlock::GrasBlock(const uint &xpos, const uint &ypos, const uint &zpos) : BaseBlock(0.0f, 1.0f, 0.0f, xpos, ypos, zpos) {
}

18
blocks/GrasBlock.h Normal file
View File

@ -0,0 +1,18 @@
//
// Created by lukas on 04.02.22.
//
#ifndef OPENGLTEST_GRASBLOCK_H
#define OPENGLTEST_GRASBLOCK_H
#include <cstdlib>
#include "BaseBlock.h"
class GrasBlock : public BaseBlock {
public:
GrasBlock(const uint &xpos, const uint &ypos, const uint &zpos);
};
#endif //OPENGLTEST_GRASBLOCK_H

48
blocks/RenderBase.cpp Normal file
View File

@ -0,0 +1,48 @@
//
// Created by lukas on 05.02.22.
//
#include "RenderBase.h"
//template<class T>
//RenderBase<T>::RenderBase() {
//
//}
//template<class T>
//void RenderBase<T>::render() {
// r.render(*va, *ib);
//}
//template<class T>
//void RenderBase<T>::init() {
// s = setShader();
// va = setVertexArray();
// ib = setIndexBuffer();
//}
//template<class T>
//void RenderBase<T>::deinit() {
//
//}
//template<class T>
//unsigned RenderBase<T>::getMVPhandle() {
// return s.getUniformHandle("MVP");
//}
//template<class T>
//unsigned RenderBase<T>::getUniformhandle(std::string name) {
// return s.getUniformHandle(std::move(name));
//}
//template<class T>
//T *RenderBase<T>::getInstance() {
// if (instance == nullptr) {
// instance = new T();
// }
// return instance;
//
//}

61
blocks/RenderBase.h Normal file
View File

@ -0,0 +1,61 @@
//
// Created by lukas on 05.02.22.
//
#ifndef OPENGLTEST_RENDERBASE_H
#define OPENGLTEST_RENDERBASE_H
#include "../gl/Renderer.h"
#include "../gl/Shader.h"
template <class T>
class RenderBase {
public:
virtual VertexArray* setVertexArray() = 0;
virtual Shader setShader() = 0;
virtual IndexBuffer* setIndexBuffer() = 0;
static RenderBase* getInstance() {
if (instance == nullptr) {
instance = new T();
instance->init();
}
return instance;
}
private:
static RenderBase* instance;
private:
Renderer r;
VertexArray* va;
IndexBuffer* ib;
Shader s;
public:
RenderBase(){};
void render(){
r.render(*va, *ib, s);
}
void init() {
s = setShader();
va = setVertexArray();
ib = setIndexBuffer();
}
void deinit(){}
unsigned getMVPhandle(){
return s.getUniformHandle("MVP");
}
unsigned getUniformhandle(std::string name){
return s.getUniformHandle(std::move(name));
}
};
template<class T>
RenderBase<T> *RenderBase<T>::instance = nullptr;
#endif //OPENGLTEST_RENDERBASE_H

20
blocks/fragment.shader Normal file
View File

@ -0,0 +1,20 @@
R"(#version 330 core
out vec4 color;
uniform vec3 u_color;
in vec3 normal;
in vec4 pos;
void main()
{
vec3 norm = normalize(normal);
vec3 lightDir = normalize(vec3(4.0,3.0,3.0) - pos.xyz);
float diff = max(dot(norm, lightDir), 0.0);
// set light color
vec3 diffuse = diff * vec3(1.0,1.0,1.0);
vec3 result = (diffuse) * u_color;
color = vec4(result,0.0);
})";

25
blocks/geometry.shader Normal file
View File

@ -0,0 +1,25 @@
R"(#version 330
layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;
out vec3 normal;
out vec4 pos;
void main( void )
{
vec3 a = ( gl_in[1].gl_Position - gl_in[0].gl_Position ).xyz;
vec3 b = ( gl_in[2].gl_Position - gl_in[0].gl_Position ).xyz;
vec3 N = normalize( cross( b, a ) );
for( int i=0; i<gl_in.length( ); ++i )
{
gl_Position = gl_in[i].gl_Position;
normal = N;
pos = gl_in[i].gl_Position;
EmitVertex( );
}
EndPrimitive( );
})";

16
blocks/vertex.shader Normal file
View File

@ -0,0 +1,16 @@
R"(#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
//// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 translation;
out vec3 FragPos;
void main(){
// Output position of the vertex, in clip space : MVP * position
vec4 pos = MVP * translation * vec4(vertexPosition_modelspace,1);
gl_Position = pos;
FragPos = pos.xyz;
})";

49
cmake/FindGLFW3.cmake Normal file
View File

@ -0,0 +1,49 @@
# Locate the glfw3 library
#
# This module defines the following variables:
#
# GLFW3_LIBRARY the name of the library;
# GLFW3_INCLUDE_DIR where to find glfw include files.
# GLFW3_FOUND true if both the GLFW3_LIBRARY and GLFW3_INCLUDE_DIR have been found.
#
# To help locate the library and include file, you can define a
# variable called GLFW3_ROOT which points to the root of the glfw library
# installation.
#
# default search dirs
#
# Cmake file from: https://github.com/daw42/glslcookbook
set( _glfw3_HEADER_SEARCH_DIRS
"/usr/include"
"/usr/local/include"
"${CMAKE_SOURCE_DIR}/include"
"C:/Program Files (x86)/glfw/include" )
set( _glfw3_LIB_SEARCH_DIRS
"/usr/lib"
"/usr/local/lib"
"${CMAKE_SOURCE_DIR}/lib"
"C:/Program Files (x86)/glfw/lib-msvc110" )
# Check environment for root search directory
set( _glfw3_ENV_ROOT $ENV{GLFW3_ROOT} )
if( NOT GLFW3_ROOT AND _glfw3_ENV_ROOT )
set(GLFW3_ROOT ${_glfw3_ENV_ROOT} )
endif()
# Put user specified location at beginning of search
if( GLFW3_ROOT )
list( INSERT _glfw3_HEADER_SEARCH_DIRS 0 "${GLFW3_ROOT}/include" )
list( INSERT _glfw3_LIB_SEARCH_DIRS 0 "${GLFW3_ROOT}/lib" )
endif()
# Search for the header
FIND_PATH(GLFW3_INCLUDE_DIR "GLFW/glfw3.h"
PATHS ${_glfw3_HEADER_SEARCH_DIRS} )
# Search for the library
FIND_LIBRARY(GLFW3_LIBRARY NAMES glfw3 glfw
PATHS ${_glfw3_LIB_SEARCH_DIRS} )
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLFW3 DEFAULT_MSG
GLFW3_LIBRARY GLFW3_INCLUDE_DIR)

57
cmake/FindGLM.cmake Normal file
View File

@ -0,0 +1,57 @@
# FindGLM - attempts to locate the glm matrix/vector library.
#
# This module defines the following variables (on success):
# GLM_INCLUDE_DIRS - where to find glm/glm.hpp
# GLM_FOUND - if the library was successfully located
#
# It is trying a few standard installation locations, but can be customized
# with the following variables:
# GLM_ROOT_DIR - root directory of a glm installation
# Headers are expected to be found in either:
# <GLM_ROOT_DIR>/glm/glm.hpp OR
# <GLM_ROOT_DIR>/include/glm/glm.hpp
# This variable can either be a cmake or environment
# variable. Note however that changing the value
# of the environment varible will NOT result in
# re-running the header search and therefore NOT
# adjust the variables set by this module.
#=============================================================================
# Copyright 2012 Carsten Neumann
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
# default search dirs
SET(_glm_HEADER_SEARCH_DIRS
"/usr/include"
"/usr/local/include"
"${CMAKE_SOURCE_DIR}/include"
"C:/Program Files (x86)/glm" )
# check environment variable
SET(_glm_ENV_ROOT_DIR "$ENV{GLM_ROOT_DIR}")
IF(NOT GLM_ROOT_DIR AND _glm_ENV_ROOT_DIR)
SET(GLM_ROOT_DIR "${_glm_ENV_ROOT_DIR}")
ENDIF(NOT GLM_ROOT_DIR AND _glm_ENV_ROOT_DIR)
# put user specified location at beginning of search
IF(GLM_ROOT_DIR)
SET(_glm_HEADER_SEARCH_DIRS "${GLM_ROOT_DIR}"
"${GLM_ROOT_DIR}/include"
${_glm_HEADER_SEARCH_DIRS})
ENDIF(GLM_ROOT_DIR)
# locate header
FIND_PATH(GLM_INCLUDE_DIR "glm/glm.hpp"
PATHS ${_glm_HEADER_SEARCH_DIRS})
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLM DEFAULT_MSG
GLM_INCLUDE_DIR)
IF(GLM_FOUND)
SET(GLM_INCLUDE_DIRS "${GLM_INCLUDE_DIR}")
MESSAGE(STATUS "GLM_INCLUDE_DIR = ${GLM_INCLUDE_DIR}")
ENDIF(GLM_FOUND)

95
gl/Camera.cpp Normal file
View File

@ -0,0 +1,95 @@
//
// Created by lukas on 05.02.22.
//
#define GL_GLEXT_PROTOTYPES
#include <valarray>
#include <glm/vec3.hpp>
#include <glm/ext/matrix_transform.hpp>
#include <GL/gl.h>
#include <glm/ext/matrix_clip_space.hpp>
#include "Camera.h"
#include "../blocks/BlockRenderer.h"
void Camera::setPos(double x, double y, double z) {
this->x = x;
this->y = y;
this->z = z;
updateCameraPos();
}
void Camera::setRotation(double rotx, double roty) {
rx = rotx;
ry = roty;
updateCameraPos();
}
void Camera::updateCameraPos() {
// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
glm::mat4 Projection = glm::perspective(glm::radians(45.0f), (float) width / (float) height, 0.1f, 100.0f);
// Or, for an ortho camera :
//glm::mat4 Projection = glm::ortho(-10.0f,10.0f,-10.0f,10.0f,0.0f,100.0f); // In world coordinates
//
// float rotation = M_PI;
//
// float x = cos(rotation);
// float y = sin(rotation);
const float radius = 5.0f;
double camX = sin(rx) * radius;
double camZ = cos(rx) * radius;
double camY = sin(ry) * radius;
glm::mat4 View = glm::lookAt(
glm::vec3(2.0f, 2.0f, 3.0f), // and looks at the origin
glm::vec3(camX, camZ, camY), // Camera is at (4,3,3), in World Space
glm::vec3(0, 0, 1) // Head is up (set to 0,-1,0 to look upside-down)
);
auto View2 = glm::translate(View, glm::vec3(x, -y, -z));
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f);
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 mvp = Projection * View2 * Model; // Remember, matrix multiplication is the other way around
// todo not really generic if we call blockrenderer here
glUniformMatrix4fv((int) BlockRenderer::getInstance()->getMVPhandle(), 1, GL_FALSE, &mvp[0][0]);
}
Camera::Camera(double width, double height) : width(width), height(height) {}
void Camera::setWindowSize(double width, double height) {
this->width = width;
this->height = height;
}
void Camera::addRotaion(double rotx, double roty) {
rx -= rotx / 300;
ry -= roty / 300;
// limit to 2pi
rx = std::fmod(rx, (2 * M_PI));
ry = std::fmod(ry, (2 * M_PI));
updateCameraPos();
}
void Camera::addPos(double x, double y, double z) {
this->x += x;
this->y += y;
this->z += z;
updateCameraPos();
}
double Camera::getxangle() const {
return rx;
}
double Camera::getyangle() const {
return ry;
}

30
gl/Camera.h Normal file
View File

@ -0,0 +1,30 @@
//
// Created by lukas on 05.02.22.
//
#ifndef OPENGLTEST_CAMERA_H
#define OPENGLTEST_CAMERA_H
class Camera {
private:
double x, y, z, rx, ry, width, height;
void updateCameraPos();
public:
Camera(double width, double height);
void setWindowSize(double width, double height);
void setPos(double x, double y, double z);
void addPos(double x, double y, double z);
void setRotation(double rotx, double roty);
void addRotaion(double rotx, double roty);
double getxangle() const;
double getyangle() const;
};
#endif //OPENGLTEST_CAMERA_H

28
gl/IndexBuffer.cpp Normal file
View File

@ -0,0 +1,28 @@
//
// Created by lukas on 03.02.22.
//
#include "IndexBuffer.h"
#include <GL/gl.h>
IndexBuffer::IndexBuffer(const unsigned *data, unsigned count): count(count) {
glGenBuffers(1, &handle);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned) * count , data, GL_STATIC_DRAW);
}
IndexBuffer::~IndexBuffer() {
glDeleteBuffers(1, &handle);
}
void IndexBuffer::Bind() const {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, handle);
}
void IndexBuffer::UnBind() const {
glBindVertexArray(0);
}
unsigned IndexBuffer::getcount() const {
return count;
}

26
gl/IndexBuffer.h Normal file
View File

@ -0,0 +1,26 @@
//
// Created by lukas on 03.02.22.
//
#ifndef OPENGLTEST_INDEXBUFFER_H
#define OPENGLTEST_INDEXBUFFER_H
#define GL_GLEXT_PROTOTYPES
class IndexBuffer {
private:
unsigned handle;
unsigned count;
public:
IndexBuffer(const unsigned *data, unsigned count);
virtual ~IndexBuffer();
void Bind() const;
void UnBind() const;
unsigned getcount() const;
};
#endif //OPENGLTEST_INDEXBUFFER_H

15
gl/Renderer.cpp Normal file
View File

@ -0,0 +1,15 @@
//
// Created by lukas on 04.02.22.
//
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include "Renderer.h"
void Renderer::render(const VertexArray& va, const IndexBuffer& ib, const Shader& s) {
va.Bind();
ib.Bind();
s.Bind();
glDrawElements(GL_TRIANGLES, ib.getcount(), GL_UNSIGNED_INT, nullptr);
}

19
gl/Renderer.h Normal file
View File

@ -0,0 +1,19 @@
//
// Created by lukas on 04.02.22.
//
#ifndef OPENGLTEST_RENDERER_H
#define OPENGLTEST_RENDERER_H
#include "VertexArray.h"
#include "IndexBuffer.h"
#include "Shader.h"
class Renderer {
public:
void render(const VertexArray& va, const IndexBuffer& ib, const Shader& s);
};
#endif //OPENGLTEST_RENDERER_H

136
gl/Shader.cpp Normal file
View File

@ -0,0 +1,136 @@
//
// Created by lukas on 03.02.22.
//
#include "Shader.h"
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include <GL/glcorearb.h>
#include <string>
#include <fstream>
#include <vector>
#include <sstream>
unsigned int Shader::compileShader(const char *source, unsigned int type) const {
unsigned int shaderid = glCreateShader(type);
// Compile Shader
glShaderSource(shaderid, 1, &source, NULL);
glCompileShader(shaderid);
// Check Shader
int Result = GL_FALSE;
int InfoLogLength;
glGetShaderiv(shaderid, GL_COMPILE_STATUS, &Result);
glGetShaderiv(shaderid, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> VertexShaderErrorMessage(InfoLogLength + 1);
glGetShaderInfoLog(shaderid, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
printf("%s\n", &VertexShaderErrorMessage[0]);
return 0;
}
return shaderid;
}
void Shader::Bind() const {
glUseProgram(mProgHandle);
}
unsigned Shader::getHandle() const {
return mProgHandle;
}
unsigned Shader::getUniformHandle(std::string name) {
if(uniformhandles.find(name) != uniformhandles.end()){
return uniformhandles[name];
}else{
const unsigned id = glGetUniformLocation(mProgHandle, name.c_str());
uniformhandles[name] = id;
return id;
}
}
std::string Shader::readFile(std::string path) {
// Read the Vertex Shader code from the file
std::string VertexShaderCode;
std::ifstream VertexShaderStream(path, std::ios::in);
if (VertexShaderStream.is_open()) {
std::stringstream sstr;
sstr << VertexShaderStream.rdbuf();
VertexShaderCode = sstr.str();
VertexShaderStream.close();
} else {
printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", path.c_str());
getchar();
return "";
}
return VertexShaderCode;
}
unsigned int Shader::loadShaderFromFile(const std::string vertex_file_path, const std::string geometry_file_path, const std::string fragment_file_path) {
// Read the Vertex Shader code from the file
std::string VertexShaderCode = readFile(vertex_file_path);
std::string FragmentShaderCode = readFile(fragment_file_path);
std::string GeometryShaderCode = readFile("../geometry.shader");
return loadShader(VertexShaderCode, GeometryShaderCode, FragmentShaderCode);
}
unsigned int Shader::loadShader(const std::string vertex_src, const std::string geometry_src, const std::string fragment_src) {
// Compile Vertex Shader
printf("Compiling vertex shader\n");
uint VertexShaderID = compileShader(vertex_src.c_str(), GL_VERTEX_SHADER);
if (VertexShaderID == 0) {
printf("Error Compiling shader\n");
return 0;
}
printf("Compiling geometry shader\n");
uint GeometryShaderID = compileShader(geometry_src.c_str(), GL_GEOMETRY_SHADER);
if (GeometryShaderID == 0) {
printf("Error Compiling shader\n");
return 0;
}
printf("Compiling fragment shader\n");
uint FragmentShaderID = compileShader(fragment_src.c_str(), GL_FRAGMENT_SHADER);
if (FragmentShaderID == 0) {
printf("Error Compiling shader\n");
return 0;
}
// Link the program
GLint Result = GL_FALSE;
int InfoLogLength;
printf("Linking shader program\n");
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, VertexShaderID);
glAttachShader(ProgramID, GeometryShaderID);
glAttachShader(ProgramID, FragmentShaderID);
glLinkProgram(ProgramID);
// Check the program
glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
if (InfoLogLength > 0) {
std::vector<char> ProgramErrorMessage(InfoLogLength + 1);
glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
printf("%s\n", &ProgramErrorMessage[0]);
}
// cleanup shaders
glDetachShader(ProgramID, VertexShaderID);
glDetachShader(ProgramID, FragmentShaderID);
glDeleteShader(VertexShaderID);
glDeleteShader(FragmentShaderID);
mProgHandle = ProgramID;
return ProgramID;
}

45
gl/Shader.h Normal file
View File

@ -0,0 +1,45 @@
//
// Created by lukas on 03.02.22.
//
#ifndef OPENGLTEST_SHADER_H
#define OPENGLTEST_SHADER_H
#include <unordered_map>
#include <string>
class Shader {
private:
unsigned mProgHandle;
std::unordered_map<std::string, unsigned> uniformhandles;
public:
/**
* load the compiled shader pipeline
* @param vertex_file_path path to vertex source file
* @param fragment_file_path path to fragment source file
* @return program id
*/
unsigned int loadShaderFromFile(const std::string vertex_file_path, const std::string geometry_file_path, const std::string fragment_file_path);
unsigned int loadShader(const std::string vertex_src, const std::string geometry_src, const std::string fragment_src);
/**
* comile a specific shader source
* @param source source string
* @param type shader tpye
* @return id of copiled shader
*/
unsigned int compileShader(const char *source, unsigned int type) const;
std::string readFile(std::string path);
void Bind() const;
unsigned getHandle() const;
unsigned getUniformHandle(std::string name);
};
#endif //OPENGLTEST_SHADER_H

26
gl/VertexArray.cpp Normal file
View File

@ -0,0 +1,26 @@
//
// Created by lukas on 04.02.22.
//
#define GL_GLEXT_PROTOTYPES
#include <GL/gl.h>
#include "VertexArray.h"
void VertexArray::Bind() const {
glBindVertexArray(handle);
}
VertexArray::VertexArray(const VertexBuffer& buff) {
buff.Bind();
// generate new vertex array object
glGenVertexArrays(1, &handle);
Bind();
// specify syntax of my data
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void *) nullptr);
glEnableVertexAttribArray(0);
}
unsigned VertexArray::getHandle() const {
return handle;
}

24
gl/VertexArray.h Normal file
View File

@ -0,0 +1,24 @@
//
// Created by lukas on 04.02.22.
//
#ifndef OPENGLTEST_VERTEXARRAY_H
#define OPENGLTEST_VERTEXARRAY_H
#include <vector>
#include "VertexBuffer.h"
class VertexArray {
private:
unsigned handle;
public:
VertexArray(const VertexBuffer& buff);
void Bind() const;
unsigned getHandle() const;
};
#endif //OPENGLTEST_VERTEXARRAY_H

25
gl/VertexBuffer.cpp Normal file
View File

@ -0,0 +1,25 @@
//
// Created by lukas on 03.02.22.
//
#include "VertexBuffer.h"
#include <GL/gl.h>
VertexBuffer::VertexBuffer(const void* data, const unsigned size) {
glGenBuffers(1, &handle);
glBindBuffer(GL_ARRAY_BUFFER, handle);
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW);
}
VertexBuffer::~VertexBuffer() {
glDeleteBuffers(1, &handle);
}
void VertexBuffer::Bind() const {
glBindBuffer(GL_ARRAY_BUFFER, handle);
}
void VertexBuffer::UnBind() const {
glBindVertexArray(0);
}

23
gl/VertexBuffer.h Normal file
View File

@ -0,0 +1,23 @@
//
// Created by lukas on 03.02.22.
//
#ifndef OPENGLTEST_VERTEXBUFFER_H
#define OPENGLTEST_VERTEXBUFFER_H
#define GL_GLEXT_PROTOTYPES
class VertexBuffer {
private:
unsigned handle;
public:
VertexBuffer(const void* data, const unsigned size);
virtual ~VertexBuffer();
void Bind() const;
void UnBind() const;
};
#endif //OPENGLTEST_VERTEXBUFFER_H

185
main.cpp Normal file
View File

@ -0,0 +1,185 @@
#include <iostream>
#define GL_GLEXT_PROTOTYPES
#include <GLFW/glfw3.h>
#include <GL/gl.h>
#include <GL/glcorearb.h>
#include "gl/Shader.h"
#include "gl/IndexBuffer.h"
#include "gl/VertexArray.h"
#include "gl/Renderer.h"
#include "blocks/GrasBlock.h"
#include "blocks/BlockRenderer.h"
#include "gl/Camera.h"
#include <cstdlib>
#include <glm/gtc/matrix_transform.hpp>
//#define WIREFRAME
void framebuffer_size_callback(GLFWwindow *window, int width, int height);
void processInput(GLFWwindow *window);
int width = 1920;
int height = 1080;
Camera cam(width, height);
double oldx = 0;
double oldy = 0;
bool menuopen = false;
void cursor_position_callback(GLFWwindow *window, double xpos, double ypos) {
if (menuopen)return;
double xdiff = oldx - xpos;
oldx = xpos;
double ydiff = oldy - ypos;
oldy = ypos;
cam.addRotaion(xdiff, ydiff);
}
GLFWwindow *initWindow() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// create new window
GLFWwindow *window = glfwCreateWindow(width, height, "LearnOpenGL", NULL, NULL);
if (window == NULL) {
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
exit(-1);
}
glfwMakeContextCurrent(window);
// limit frame rate
glfwSwapInterval(1);
// set window viewport
glViewport(0, 0, width, height);
// callback when window was resized
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
glfwSetCursorPosCallback(window, cursor_position_callback);
if (glfwRawMouseMotionSupported())
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
std::cout << "[GLFW] " << glfwGetVersionString() << std::endl;
std::cout << "[GL] " << glGetString(GL_VERSION) << std::endl;
return window;
}
int main() {
GLFWwindow *window = initWindow();
#ifdef WIREFRAME
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
#endif
glEnable(GL_DEPTH_TEST);
GrasBlock gb(0, 0, 0);
BaseBlock bb(0.0f, (float) rand() / RAND_MAX, 1.0f, 1, 0, 0);
// BlockRenderer::getInstance()->init();
std::vector<BaseBlock> blocks;
blocks.push_back(gb);
blocks.push_back(bb);
blocks.emplace_back(1.0f, .0f, 1.0f, 0, 0, 1);
for (int i = 0; i < 5; i++) {
blocks.push_back(GrasBlock(i, i, 0));
}
cam.setPos(0, 0, 0);
cam.setRotation(0,0);
while (!glfwWindowShouldClose(window)) {
// process user input events
processInput(window);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (auto b: blocks) {
b.render();
}
// swap buffer to calc and show
glfwSwapBuffers(window);
// poll for and execute events
glfwPollEvents();
}
// glDeleteProgram(shaderProgram);
BlockRenderer::getInstance()->deinit();
glfwTerminate();
return 0;
}
// callback when user resizes image
void framebuffer_size_callback(GLFWwindow *window, int width, int height) {
glViewport(0, 0, width, height);
cam.setWindowSize(width, height);
}
void processInput(GLFWwindow *window) {
// 45c view range
double viewrange = M_PI / 8;
if (!menuopen) {
if (glfwGetKey(window, GLFW_KEY_W)) {
cam.addPos(-sin(cam.getxangle() - viewrange) * 0.1, cos(cam.getxangle() + viewrange) * 0.1, 0.0);
}
if (glfwGetKey(window, GLFW_KEY_S)) {
cam.addPos(sin(cam.getxangle() + viewrange) * 0.1, -cos(cam.getxangle() - viewrange) * 0.1, 0.0);
}
if (glfwGetKey(window, GLFW_KEY_D)) {
cam.addPos(sin(cam.getxangle() - M_PI / 2) * 0.1, -cos(cam.getxangle() - M_PI / 2) * 0.1, 0.0);
}
if (glfwGetKey(window, GLFW_KEY_A)) {
cam.addPos(sin(cam.getxangle() + M_PI / 2) * 0.1, -cos(cam.getxangle() + M_PI / 2) * 0.1, 0.0);
}
if (glfwGetKey(window, GLFW_KEY_SPACE)) {
cam.addPos(0.0,0.0,0.1);
}
if (glfwGetKey(window, GLFW_KEY_LEFT_SHIFT)) {
cam.addPos(0.0,0.0,-0.1);
}
}
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
menuopen = !menuopen;
glfwSetInputMode(window, GLFW_CURSOR, menuopen ? GLFW_CURSOR_NORMAL : GLFW_CURSOR_DISABLED);
// reset old cursor pos to new one to avoid a jump
glfwGetCursorPos(window, &oldx, &oldy);
}
// glfwSetWindowShouldClose(window, true);
}