More preparation for the legendary triangle. Currently working on Batch.h

to specify the batch pipeline specified at StackOverflow
See https://stackoverflow.com/questions/8923174/opengl-vao-best-practices#8923298
This commit is contained in:
elipzer 2018-09-05 11:47:09 -04:00
parent 34ba510e43
commit 40617c8953
31 changed files with 286 additions and 113 deletions

View File

@ -1,14 +1,11 @@
#include "Application.h"
#include <Windows.h>
#include <glew/glew.h>
#include <gl/GL.h>
#pragma comment(lib, "opengl32.lib")
#include "Exception.h"
Application::Application(const char* class_name, HINSTANCE h_instance)
: m_window(class_name, h_instance), m_input_manager(&m_window.get_input_manager()), m_client_size(1280, 720)
{
base_init();
}
@ -25,8 +22,7 @@ Application::~Application()
int Application::run()
{
if (!base_init()) return 1;
init();
MessageResponse resp(UNSET);
while (resp != QUIT_MESSAGE) {
// Handle all messages
@ -45,10 +41,10 @@ void Application::close()
{
}
bool Application::base_init()
void Application::base_init()
{
if (!m_window.register_class()) return false;
if (!m_window.create_window("OpenGLEngine", -1, -1, m_client_size.x, m_client_size.y)) return false;
if (!m_window.register_class()) throw EXCEPTION("Unable to register window class.");
if (!m_window.create_window("OpenGLEngine", -1, -1, m_client_size.x, m_client_size.y)) throw EXCEPTION("Unable to create window");
// Initialize window with OpenGL (May want to move this into MyApplication to allow application customization)
// https://www.khronos.org/opengl/wiki/Creating_an_OpenGL_Context_(WGL)
@ -70,12 +66,23 @@ bool Application::base_init()
SetPixelFormat(device_context, pixel_format, &pfd);
m_window.set_h_glrc(wglCreateContext(m_window.get_h_dc()));
HGLRC glrc = wglCreateContext(m_window.get_h_dc());
wglMakeCurrent(device_context, glrc);
m_window.set_h_glrc(glrc);
GLenum glewErr = glewInit();
if (glewErr != GLEW_OK)
{
OutputDebugString("Glew Init Failed: ");
OutputDebugString((char*)glewGetErrorString(glewErr));
OutputDebugString("\n");
throw EXCEPTION("GLEW Init Failure");
}
m_window.show(SW_NORMAL);
m_fps.prepare();
return init();
}
void Application::base_close()

View File

@ -1,6 +1,6 @@
#pragma once
#include <Windows.h>
#include "stdafx.h"
#include "vec2.h"
@ -19,7 +19,7 @@ public:
protected:
// Called on initialization of the application (called by base_init)
virtual bool init() = 0;
virtual void init() = 0;
virtual void update(float delta_time, clock_t clock) = 0;
@ -40,7 +40,7 @@ protected:
// The FPS counter of this application
FPS m_fps;
private:
bool base_init();
void base_init();
void base_close();
};

20
OpenGLEngine/Batch.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <vector>
#include "ShaderProgram.h"
#include "Renderable.h"
template <typename VertexType, typename IndexType>
class Batch
{
public:
Batch(ShaderProgram* p_shader_program, const std::vector<Renderable<VertexType, IndexType>*>& p_renderables);
virtual void init() = 0; // Maybe make this automatic? Or in the constructor?
virtual void render() = 0;
private:
ShaderProgram* m_p_shader_program;
std::vector<Renderable<VertexType, IndexType>*> m_p_renderables;
};

View File

@ -0,0 +1,16 @@
#include "Exception.h"
Exception::Exception(const std::string& message, const std::string& class_name)
: m_message(message), m_class_name(class_name)
{
}
const std::string& Exception::get_message()
{
return m_message;
}
const std::string& Exception::get_class_name()
{
return m_class_name;
}

19
OpenGLEngine/Exception.h Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <string>
// TODO: This MUST be changed to something less generic
#define EXCEPTION(message) Exception(message, typeid(*this).name())
class Exception
{
public:
Exception(const std::string& message, const std::string& class_name);
const std::string& get_message();
const std::string& get_class_name();
private:
std::string m_message;
std::string m_class_name;
};

10
OpenGLEngine/Mesh.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
template <typename VertexType, typename IndexType>
struct Mesh
{
VertexType* vertices = nullptr;
unsigned int vertex_count = 0;
IndexType* indices = nullptr;
unsigned int index_count = 0;
};

View File

@ -10,10 +10,10 @@ MyApplication::~MyApplication()
{
}
bool MyApplication::init()
void MyApplication::init()
{
m_scene.init();
m_scene.use();
return true;
}
void MyApplication::update(float delta_time, clock_t clock)

View File

@ -10,7 +10,7 @@ public:
MyApplication(const char* class_name, HINSTANCE h_instance);
~MyApplication();
bool init() override;
void init() override;
void update(float delta_time, clock_t clock) override;

11
OpenGLEngine/MyBatch.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "MyBatch.h"
void MyBatch::init()
{
// TODO
}
void MyBatch::render()
{
// TODO
}

9
OpenGLEngine/MyBatch.h Normal file
View File

@ -0,0 +1,9 @@
#pragma once
#include "Batch.h"
class MyBatch : public Batch
{
void init() override;
void render() override;
};

View File

@ -4,8 +4,8 @@
MyShaderProgram::MyShaderProgram()
// TEMP Hardcode in the path
: m_vertex_shader(Util::load_file("D:\\Development\\C++\\OpenGLEngine\\OpenGLEngine\\MyVertexShader.glsl").data(), VERTEX_SHADER),
m_fragment_shader(Util::load_file("D:\\Development\\C++\\OpenGLEngine\\OpenGLEngine\\MyFragmentShader.glsl").data(), FRAGMENT_SHADER)
: m_vertex_shader(Util::load_file("D:\\Development\\C++\\OpenGLEngine\\OpenGLEngine\\MyVertexShader.glsl"), VERTEX_SHADER),
m_fragment_shader(Util::load_file("D:\\Development\\C++\\OpenGLEngine\\OpenGLEngine\\MyFragmentShader.glsl"), FRAGMENT_SHADER)
{
attach_shader(m_vertex_shader);
attach_shader(m_fragment_shader);

View File

@ -13,6 +13,8 @@ public:
float z;
};
typedef unsigned int Index;
MyShaderProgram();
protected:

View File

@ -9,6 +9,12 @@ MySimpleScene::~MySimpleScene()
{
}
void MySimpleScene::init()
{
m_shader_program.init();
m_triangle.init();
}
void MySimpleScene::use()
{
}
@ -25,5 +31,5 @@ void MySimpleScene::render()
{
m_shader_program.use();
glBindBuffer(GL_ARRAY_BUFFER, m_triangle.get_vbo());
glDrawArrays(GL_TRIANGLES, 0, m_triangle.get_vertex_count());
glDrawArrays(GL_TRIANGLES, 0, 3);
}

View File

@ -15,6 +15,8 @@ public:
MySimpleScene();
~MySimpleScene();
void init() override;
void use() override;
void unuse() override;

View File

@ -1,31 +1,37 @@
#include "MyTriangle.h"
#include "Mesh.h"
MyTriangle::MyTriangle()
{
MeshType* mesh = new MeshType();
mesh->vertices = new VertexType[3]
{
{ 0.0, 0.5, 1.0 },
{ 0.5, -0.5, 1.0 },
{ -0.5, -0.5, 1.0 },
};
mesh->vertex_count = 3;
mesh->indices = new unsigned int[3] { 0, 1, 2, };
mesh->index_count = 3;
m_p_mesh = mesh;
}
MyTriangle::~MyTriangle()
{
}
const MyTriangle::VertexType* MyTriangle::get_vertices() const
{
return m_vertices;
}
const unsigned int MyTriangle::get_vertex_count() const
{
return m_vertex_count;
}
const MyTriangle::IndexType* MyTriangle::get_indices() const
{
return m_indices;
}
const unsigned int MyTriangle::get_index_count() const
{
return m_index_count;
if (m_p_mesh != nullptr)
{
if (m_p_mesh->vertices != nullptr)
{
delete[] m_p_mesh->vertices;
}
if (m_p_mesh->indices != nullptr)
{
delete[] m_p_mesh->indices;
}
delete m_p_mesh;
m_p_mesh = nullptr;
}
}
GLuint MyTriangle::gen_vbo() const
@ -33,7 +39,7 @@ GLuint MyTriangle::gen_vbo() const
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, m_vertex_count * sizeof(VertexType), m_vertices, GL_STATIC_DRAW); // TODO: Optimise Usage
glBufferData(GL_ARRAY_BUFFER, m_p_mesh->vertex_count * sizeof(VertexType), m_p_mesh->vertices, GL_STATIC_DRAW); // TODO: Optimise Usage
return vbo;
}

View File

@ -4,33 +4,16 @@
#include "MyShaderProgram.h"
class MyTriangle : public Renderable<MyShaderProgram::Vertex>
class MyTriangle : public Renderable<MyShaderProgram::Vertex, MyShaderProgram::Index>
{
public:
MyTriangle();
~MyTriangle();
const VertexType* get_vertices() const override;
const unsigned int get_vertex_count() const override;
const IndexType* get_indices() const override;
const unsigned int get_index_count() const override;
protected:
GLuint gen_vbo() const override;
private:
const unsigned int m_vertex_count = 3;
const VertexType m_vertices[3] =
{
{ 0.0f, 0.5f, 0.0f },
{ 0.5f, -0.5f, 0.0f },
{ -0.5f, -0.5f, 0.0f },
};
const unsigned int m_index_count = 3;
const IndexType m_indices[3] =
{
0, 1, 2,
};
};

View File

@ -69,7 +69,12 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LibraryPath>D:\Development\C++\OpenGLEngine\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LibraryPath>D:\Development\C++\OpenGLEngine\lib;$(LibraryPath)</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@ -85,10 +90,9 @@
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<Link>
<AdditionalDependencies>opengl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<Link />
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@ -112,7 +116,8 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>C:\Users\peterm8\source\repos\OpenGLEngine\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir)..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@ -121,6 +126,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Application.cpp" />
<ClCompile Include="Exception.cpp" />
<ClCompile Include="FPS.cpp" />
<ClCompile Include="InputManager.cpp" />
<ClCompile Include="main.cpp" />
@ -130,14 +136,20 @@
<ClCompile Include="MyTriangle.cpp" />
<ClCompile Include="Shader.cpp" />
<ClCompile Include="ShaderProgram.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Util.cpp" />
<ClCompile Include="Window.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Application.h" />
<ClInclude Include="Exception.h" />
<ClInclude Include="FPS.h" />
<ClInclude Include="InputManager.h" />
<ClInclude Include="mat4x4.h" />
<ClInclude Include="Mesh.h" />
<ClInclude Include="MyApplication.h" />
<ClInclude Include="MyShaderProgram.h" />
<ClInclude Include="MySimpleScene.h" />
@ -146,6 +158,7 @@
<ClInclude Include="Scene.h" />
<ClInclude Include="Shader.h" />
<ClInclude Include="ShaderProgram.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="Util.h" />
<ClInclude Include="vec2.h" />
<ClInclude Include="vec3.h" />

View File

@ -63,6 +63,12 @@
<ClCompile Include="MyShaderProgram.cpp">
<Filter>Source Files\Example</Filter>
</ClCompile>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Exception.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Window.h">
@ -116,6 +122,15 @@
<ClInclude Include="MyShaderProgram.h">
<Filter>Header Files\Example</Filter>
</ClInclude>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Exception.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Mesh.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="MyVertexShader.glsl">

View File

@ -1,31 +1,30 @@
#pragma once
#include "stdafx.h"
#include <type_traits>
#include <Windows.h>
#include <glew/glew.h>
#include <gl/GL.h>
#include "Mesh.h"
#pragma comment(lib, "opengl32.lib")
template <typename VertexType>
template <typename VertexType, typename IndexType>
class Renderable
{
public:
typedef VertexType VertexType;
typedef unsigned int IndexType;
typedef IndexType IndexType;
typedef Mesh<VertexType, IndexType> MeshType;
Renderable()
virtual ~Renderable() { };
void init()
{
m_vbo = gen_vbo();
}
virtual ~Renderable() { };
virtual const VertexType* get_vertices() const = 0;
virtual const unsigned int get_vertex_count() const = 0;
virtual const IndexType* get_indices() const = 0;
virtual const unsigned int get_index_count() const = 0;
const MeshType* get_mesh() const
{
return m_p_mesh;
}
GLuint get_vbo() const
{
@ -35,5 +34,6 @@ public:
protected:
virtual GLuint gen_vbo() const = 0;// TODO: A VBO for every object?
GLuint m_vbo;
const MeshType* m_p_mesh = nullptr;
GLuint m_vbo = 0;
};

View File

@ -1,5 +1,7 @@
#pragma once
#include "stdafx.h"
#include <time.h>
class Scene
@ -7,6 +9,9 @@ class Scene
public:
virtual ~Scene() { };
// Called when the scene is ready to be initialized
virtual void init() = 0;
// Called when the scene is going to be used
// Should allocate all graphics memory.
virtual void use() = 0;

View File

@ -1,7 +1,10 @@
#include "Shader.h"
Shader::Shader(const char* source, ShaderType type)
: m_type(type)
#include <Windows.h>
#include "Exception.h"
Shader::Shader(const std::string& source, ShaderType type)
{
GLenum gl_shader_type;
switch (type)
@ -18,7 +21,9 @@ Shader::Shader(const char* source, ShaderType type)
m_shader = glCreateShader(gl_shader_type);
glShaderSource(m_shader, 1, &source, NULL);
const char* c_str = source.c_str();
glShaderSource(m_shader, 1, &c_str, NULL);
glCompileShader(m_shader);
// Make sure that the shader has been compiled successfully
@ -32,8 +37,11 @@ Shader::Shader(const char* source, ShaderType type)
buffer[log_length] = '\0'; // Add null terminator
OutputDebugString("Error Compiling Shader:\n");
OutputDebugString(buffer);
OutputDebugString("\nSource:\n");
OutputDebugString(source.c_str());
OutputDebugString("\n");
m_shader = 0;
throw "Error compiling shader.";
throw EXCEPTION("Error compiling shader.");
}
}

View File

@ -1,10 +1,6 @@
#pragma once
#include <Windows.h>
#include <glew/glew.h>
#include <gl/GL.h>
#pragma comment(lib, "opengl32.lib")
#include "stdafx.h"
#include <string>
@ -17,13 +13,12 @@ enum ShaderType
class Shader
{
public:
Shader(const char* source, ShaderType type);
Shader(const std::string& source, ShaderType type);
~Shader();
GLuint get_shader() const;
private:
GLuint m_shader;
ShaderType m_type;
};

View File

@ -3,7 +3,6 @@
ShaderProgram::ShaderProgram()
{
m_program = glCreateProgram();
m_vao = gen_vao();
}
ShaderProgram::~ShaderProgram()
@ -11,6 +10,11 @@ ShaderProgram::~ShaderProgram()
glDeleteProgram(m_program);
}
void ShaderProgram::init()
{
m_vao = gen_vao();
}
void ShaderProgram::attach_shader(const Shader& shader)
{
glAttachShader(m_program, shader.get_shader());

View File

@ -1,10 +1,8 @@
#pragma once
#include <Windows.h>
#include <glew/glew.h>
#include <gl/GL.h>
#include "stdafx.h"
#pragma comment(lib, "opengl32.lib")
#include "Exception.h"
#include "Shader.h"
@ -14,6 +12,7 @@ public:
ShaderProgram();
virtual ~ShaderProgram();
void init();
void use();
GLuint get_program() const;
@ -27,6 +26,6 @@ protected:
virtual GLuint gen_vao() const = 0;
private:
GLuint m_program;
GLuint m_vao;
GLuint m_program = 0;
GLuint m_vao = 0;
};

View File

@ -1,17 +1,32 @@
#include "Util.h"
#include <fstream>
#include <string>
std::vector<char> Util::load_file(const std::string& path)
#include "Exception.h"
std::string Util::load_file(const std::string& path)
{
std::ifstream input_stream(path, std::ios::binary | std::ios::in | std::ios::ate);
if (input_stream)
std::ifstream input_stream;
try
{
std::streampos size = input_stream.tellg();
input_stream.seekg(std::ios::beg);
std::vector<char> buffer(size);
input_stream.read(buffer.data(), size);
input_stream.close();
input_stream.open(path);
}
catch (std::ios::failure& e)
{
throw Exception(std::string("Error Opening File: ") + e.what(), "class Util");
}
if (input_stream.is_open())
{
input_stream.seekg(0, std::ios::end);
size_t size = input_stream.tellg();
std::string buffer(size, ' ');
input_stream.seekg(std::ios::beg);
input_stream.read(&buffer[0], size);
return buffer;
}
else
{
throw Exception("Unable to access file: " + path, "class Util");
}
throw "Unable to access file.";
}

View File

@ -6,5 +6,5 @@
class Util
{
public:
static std::vector<char> load_file(const std::string& path);
static std::string load_file(const std::string& path);
};

View File

@ -1,6 +1,6 @@
#pragma once
#include <Windows.h>
#include "stdafx.h"
#include "InputManager.h"

View File

@ -1,7 +1,27 @@
#include "stdafx.h"
#include <Windows.h>
#include <string>
#include "Exception.h"
#include "MyApplication.h"
int WINAPI WinMain(HINSTANCE h_instance, HINSTANCE h_prev_instance, LPSTR cmd_line, int n_cmd_show)
{
MyApplication my_app("my_app", h_instance);
return my_app.run();
try
{
MyApplication my_app("my_app", h_instance);
return my_app.run();
}
catch (Exception& e)
{
OutputDebugString("Caught Exception: [");
OutputDebugString(e.get_class_name().c_str());
OutputDebugString("]: ");
OutputDebugString(e.get_message().c_str());
OutputDebugString("\n");
return 1;
}
}

2
OpenGLEngine/stdafx.cpp Normal file
View File

@ -0,0 +1,2 @@
#include "stdafx.h"

6
OpenGLEngine/stdafx.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <glew/glew.h>
#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "opengl32.lib")

BIN
lib/glew32.lib Normal file

Binary file not shown.