add rudimentary shaders and machinery

This commit is contained in:
Chris Sarbora 2024-07-20 16:19:31 -05:00
parent bc99cc867b
commit d61deae68d
No known key found for this signature in database
8 changed files with 371 additions and 11 deletions

31
cmake/shaders.cmake Normal file
View File

@ -0,0 +1,31 @@
file(WRITE ${shaders_h} "#pragma once
#include <string_view>
namespace shaders {
")
set(idx 0)
set(idx_is_path FALSE)
while(${idx} LESS ${CMAKE_ARGC})
if(idx_is_path)
set(shader_path ${CMAKE_ARGV${idx}})
cmake_path(GET shader_path STEM shader_name)
file(READ ${shader_path} content)
file(APPEND ${shaders_h} "
inline constexpr std::string_view ${shader_name} = R\"shader(${content}
)shader\";
")
else()
if(${CMAKE_ARGV${idx}} STREQUAL "--")
set(idx_is_path TRUE)
endif()
endif()
math(EXPR idx "${idx} + 1")
endwhile()
foreach(idx RANGE ${CMAKE_ARGC})
endforeach()
file(APPEND ${shaders_h} "
} // namespace shaders
")

41
misc/holder.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Descent 3
* Copyright (C) 2024 Descent Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <utility>
template <typename T, void (*Deleter)(T)>
struct MoveOnlyHolder {
MoveOnlyHolder(T t)
: t_{std::move(t)} {}
MoveOnlyHolder(MoveOnlyHolder&& other)
: t_{std::exchange(other.t_, {})} {}
~MoveOnlyHolder() noexcept {
Deleter(t_);
}
operator T() const {
return t_;
}
private:
T t_;
};

View File

@ -1,6 +1,21 @@
cmake_path(SET GENERATED_HEADERS NORMALIZE ${CMAKE_CURRENT_BINARY_DIR}/generated)
cmake_path(SET SHADERS_H NORMALIZE ${GENERATED_HEADERS}/shaders.h)
set(SHADERS
shaders/fragment.glsl
shaders/vertex.glsl
)
add_custom_command(
OUTPUT ${SHADERS_H}
COMMAND ${CMAKE_COMMAND} -Dshaders_h=${SHADERS_H} -P ../cmake/shaders.cmake -- ${SHADERS}
DEPENDS ../cmake/shaders.cmake ${SHADERS}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
set(HEADERS set(HEADERS
dyna_gl.h dyna_gl.h
HardwareInternal.h HardwareInternal.h
ShaderProgram.h
${SHADERS_H}
) )
set(CPPS set(CPPS
HardwareClipper.cpp HardwareClipper.cpp
@ -15,12 +30,8 @@ set(CPPS
lnxscreenmode.cpp lnxscreenmode.cpp
) )
# These are excluded.
#opengl.cpp
#renderer.cpp
#Direct3D.cpp
add_library(renderer STATIC ${HEADERS} ${CPPS}) add_library(renderer STATIC ${HEADERS} ${CPPS})
target_include_directories(renderer PRIVATE ${GENERATED_HEADERS})
target_link_libraries(renderer PRIVATE target_link_libraries(renderer PRIVATE
SDL2::SDL2 SDL2::SDL2
bitmap bitmap

View File

@ -21,12 +21,16 @@
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
#include <optional>
#include <SDL.h> #include <SDL.h>
#if defined(WIN32) #if defined(WIN32)
#include <windows.h> #include <windows.h>
#endif #endif
#define DECLARE_OPENGL
#include "dyna_gl.h"
#include "byteswap.h" #include "byteswap.h"
#include "pserror.h" #include "pserror.h"
#include "mono.h" #include "mono.h"
@ -43,9 +47,8 @@
#include "HardwareInternal.h" #include "HardwareInternal.h"
#include "../Descent3/args.h" #include "../Descent3/args.h"
#include "NewBitmap.h" #include "NewBitmap.h"
#include "shaders.h"
#define DECLARE_OPENGL #include "ShaderProgram.h"
#include "dyna_gl.h"
#if defined(WIN32) #if defined(WIN32)
#include "win/arb_extensions.h" #include "win/arb_extensions.h"
@ -64,6 +67,21 @@ extern uint8_t Renderer_initted;
renderer_type Renderer_type = RENDERER_OPENGL; renderer_type Renderer_type = RENDERER_OPENGL;
int WindowGL = 0; int WindowGL = 0;
struct Renderer {
Renderer() : shader_{shaders::vertex, shaders::fragment, {
vertexAttrib(3, GL_FLOAT, GL_FALSE, &PosColorUV2Vertex::pos, "in_pos"),
vertexAttrib(4, GL_FLOAT, GL_FALSE, &PosColorUV2Vertex::color, "in_color"),
vertexAttrib(2, GL_FLOAT, GL_FALSE, &PosColorUV2Vertex::uv0, "in_uv0"),
vertexAttrib(2, GL_FLOAT, GL_FALSE, &PosColorUV2Vertex::uv1, "in_uv1")
}} {
shader_.Use();
}
private:
ShaderProgram<PosColorUV2Vertex> shader_;
};
std::optional<Renderer> gRenderer;
#ifndef GL_UNSIGNED_SHORT_5_5_5_1 #ifndef GL_UNSIGNED_SHORT_5_5_5_1
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 #define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
#endif #endif
@ -502,6 +520,8 @@ int opengl_Setup(oeApplication *app, int *width, int *height) {
reinterpret_cast<oeLnxApplication *>(ParentApplication)->set_sizepos(0, 0, *width, *height); reinterpret_cast<oeLnxApplication *>(ParentApplication)->set_sizepos(0, 0, *width, *height);
} }
gRenderer.emplace();
Already_loaded = 1; Already_loaded = 1;
return 1; return 1;
} }
@ -700,6 +720,8 @@ void opengl_Close(const bool just_resizing) {
mem_free(delete_list); mem_free(delete_list);
gRenderer.reset();
if (GSDLGLContext) { if (GSDLGLContext) {
SDL_GL_MakeCurrent(NULL, NULL); SDL_GL_MakeCurrent(NULL, NULL);
SDL_GL_DeleteContext(GSDLGLContext); SDL_GL_DeleteContext(GSDLGLContext);

179
renderer/ShaderProgram.h Normal file
View File

@ -0,0 +1,179 @@
/*
* Descent 3
* Copyright (C) 2024 Descent Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstddef>
#include <functional>
#include <stdexcept>
#include <string>
#include "dyna_gl.h"
#include "holder.h"
template <typename E>
struct VertexAttrib {
using EnclosingType = E;
GLint size;
GLenum type;
GLboolean normalized;
uintptr_t offset;
std::string name;
};
template <typename EnclosingType, typename MemberType>
VertexAttrib<EnclosingType> vertexAttrib(GLint size, GLenum type, GLboolean normalized, MemberType EnclosingType::*member, std::string name) {
EnclosingType e;
return VertexAttrib<EnclosingType>{
size,
type,
normalized,
reinterpret_cast<uintptr_t>(&(e.*member)) - reinterpret_cast<uintptr_t>(&e),
std::move(name)
};
}
template <typename V>
struct VertexBuffer {
VertexBuffer(GLuint program,
std::vector<VertexAttrib<V>> attribs,
size_t vertex_count,
GLenum bufferType,
V const* initialData = nullptr)
: vao_{outval(dglGenVertexArrays)},
vbo_{outval(dglGenBuffers)} {
dglBindVertexArray(vao_);
dglBindBuffer(GL_ARRAY_BUFFER, vbo_);
dglBufferData(GL_ARRAY_BUFFER,
vertex_count * sizeof(PosColorUV2Vertex),
initialData,
bufferType);
for (GLint i{}; i < attribs.size(); i++) {
dglEnableVertexAttribArray(i);
dglVertexAttribPointer(i,
attribs[i].size,
attribs[i].type,
attribs[i].normalized,
sizeof(V),
reinterpret_cast<void*>(attribs[i].offset));
dglBindAttribLocation(program, i, attribs[i].name.c_str());
}
}
void UpdateData(size_t vtx_offset, size_t vtx_count, V const* vertices) const {
dglBindBuffer(GL_ARRAY_BUFFER, vbo_);
dglBufferSubData(GL_ARRAY_BUFFER, vtx_offset * sizeof(V), vtx_count * sizeof(V), vertices);
}
private:
static void DeleteBuffer(GLuint id) {
dglDeleteBuffers(1, &id);
}
static void DeleteVertexArray(GLuint id) {
dglDeleteVertexArrays(1, &id);
}
template <typename Generator>
GLuint outval(Generator&& gen) {
GLuint id;
gen(1, &id);
return id;
}
MoveOnlyHolder<GLuint, DeleteVertexArray> vao_;
MoveOnlyHolder<GLuint, DeleteBuffer> vbo_;
};
template <GLenum kType>
struct Shader {
static_assert(kType == GL_VERTEX_SHADER || kType == GL_FRAGMENT_SHADER);
explicit Shader(std::string_view src)
: id_{dglCreateShader(kType)} {
if (id_ == 0) {
throw std::runtime_error("failed to create shader");
}
char const* srcptr = src.data();
GLint srclen = src.size();
dglShaderSource(id_, 1, &srcptr, &srclen);
dglCompileShader(id_);
GLint compile_result;
dglGetShaderiv(id_, GL_COMPILE_STATUS, &compile_result);
if (compile_result != GL_TRUE) {
GLsizei log_length = 0;
GLchar message[1024];
dglGetShaderInfoLog(id_, 1024, &log_length, message);
throw std::runtime_error(std::string{message, static_cast<size_t>(log_length)});
}
}
GLuint id() const {
ASSERT(id_ != 0);
return id_;
}
private:
static void DeleteShader(GLuint id) {
dglDeleteShader(id);
}
MoveOnlyHolder<GLuint, DeleteShader> id_;
};
template <typename V>
struct ShaderProgram {
explicit ShaderProgram(std::string_view vertexSrc, std::string_view fragmentSrc, std::vector<VertexAttrib<V>> attribs)
: id_{dglCreateProgram()}, vertex_{vertexSrc}, fragment_{fragmentSrc}, vbo_{id_, std::move(attribs), MAX_POINTS_IN_POLY, GL_DYNAMIC_DRAW} {
if (id_ == 0) {
throw std::runtime_error("error creating GL program");
}
dglAttachShader(id_, vertex_.id());
dglAttachShader(id_, fragment_.id());
dglLinkProgram(id_);
GLint link_result;
dglGetProgramiv(id_, GL_LINK_STATUS, &link_result);
if (link_result != GL_TRUE)
{
GLsizei log_length = 0;
GLchar message[1024];
dglGetProgramInfoLog(id_, 1024, &log_length, message);
throw std::runtime_error(std::string{message, static_cast<size_t>(log_length)});
}
}
void Use() const {
dglUseProgram(id_);
}
void Unuse() const {
dglUseProgram(0);
}
private:
static void DeleteProgram(GLuint id) {
dglDeleteProgram(id);
}
MoveOnlyHolder<GLuint, DeleteProgram> id_;
Shader<GL_VERTEX_SHADER> vertex_;
Shader<GL_FRAGMENT_SHADER> fragment_;
VertexBuffer<V> vbo_;
};

View File

@ -146,15 +146,28 @@ static module *LoadOpenGLDLL(const char *dllname) {
#define DYNAEXTERN(Name) extern FnPtr<decltype(Name)> const d##Name #define DYNAEXTERN(Name) extern FnPtr<decltype(Name)> const d##Name
#endif #endif
DYNAEXTERN(glAttachShader);
DYNAEXTERN(glBindAttribLocation);
DYNAEXTERN(glBindBuffer);
DYNAEXTERN(glBindTexture); DYNAEXTERN(glBindTexture);
DYNAEXTERN(glBindVertexArray);
DYNAEXTERN(glBlendFunc); DYNAEXTERN(glBlendFunc);
DYNAEXTERN(glBufferData);
DYNAEXTERN(glBufferSubData);
DYNAEXTERN(glClear); DYNAEXTERN(glClear);
DYNAEXTERN(glClearColor); DYNAEXTERN(glClearColor);
DYNAEXTERN(glColor3ub); DYNAEXTERN(glColor3ub);
DYNAEXTERN(glColor4f); DYNAEXTERN(glColor4f);
DYNAEXTERN(glColor4ub); DYNAEXTERN(glColor4ub);
DYNAEXTERN(glColorPointer); DYNAEXTERN(glColorPointer);
DYNAEXTERN(glCompileShader);
DYNAEXTERN(glCreateProgram);
DYNAEXTERN(glCreateShader);
DYNAEXTERN(glDeleteBuffers);
DYNAEXTERN(glDeleteProgram);
DYNAEXTERN(glDeleteShader);
DYNAEXTERN(glDeleteTextures); DYNAEXTERN(glDeleteTextures);
DYNAEXTERN(glDeleteVertexArrays);
DYNAEXTERN(glDepthFunc); DYNAEXTERN(glDepthFunc);
DYNAEXTERN(glDepthMask); DYNAEXTERN(glDepthMask);
DYNAEXTERN(glDepthRange); DYNAEXTERN(glDepthRange);
@ -163,15 +176,23 @@ DYNAEXTERN(glDisableClientState);
DYNAEXTERN(glDrawArrays); DYNAEXTERN(glDrawArrays);
DYNAEXTERN(glEnable); DYNAEXTERN(glEnable);
DYNAEXTERN(glEnableClientState); DYNAEXTERN(glEnableClientState);
DYNAEXTERN(glEnableVertexAttribArray);
DYNAEXTERN(glFlush); DYNAEXTERN(glFlush);
DYNAEXTERN(glFogf); DYNAEXTERN(glFogf);
DYNAEXTERN(glFogfv); DYNAEXTERN(glFogfv);
DYNAEXTERN(glFogi); DYNAEXTERN(glFogi);
DYNAEXTERN(glGenBuffers);
DYNAEXTERN(glGenVertexArrays);
DYNAEXTERN(glGetError); DYNAEXTERN(glGetError);
DYNAEXTERN(glGetIntegerv); DYNAEXTERN(glGetIntegerv);
DYNAEXTERN(glGetProgramInfoLog);
DYNAEXTERN(glGetProgramiv);
DYNAEXTERN(glGetShaderInfoLog);
DYNAEXTERN(glGetShaderiv);
DYNAEXTERN(glGetString); DYNAEXTERN(glGetString);
DYNAEXTERN(glGetStringi); DYNAEXTERN(glGetStringi);
DYNAEXTERN(glHint); DYNAEXTERN(glHint);
DYNAEXTERN(glLinkProgram);
DYNAEXTERN(glLoadIdentity); DYNAEXTERN(glLoadIdentity);
DYNAEXTERN(glLoadMatrixf); DYNAEXTERN(glLoadMatrixf);
DYNAEXTERN(glMatrixMode); DYNAEXTERN(glMatrixMode);
@ -180,6 +201,7 @@ DYNAEXTERN(glPixelStorei);
DYNAEXTERN(glPolygonOffset); DYNAEXTERN(glPolygonOffset);
DYNAEXTERN(glReadPixels); DYNAEXTERN(glReadPixels);
DYNAEXTERN(glScissor); DYNAEXTERN(glScissor);
DYNAEXTERN(glShaderSource);
DYNAEXTERN(glTexCoord2f); DYNAEXTERN(glTexCoord2f);
DYNAEXTERN(glTexCoord4fv); DYNAEXTERN(glTexCoord4fv);
DYNAEXTERN(glTexCoordPointer); DYNAEXTERN(glTexCoordPointer);
@ -187,9 +209,8 @@ DYNAEXTERN(glTexEnvf);
DYNAEXTERN(glTexImage2D); DYNAEXTERN(glTexImage2D);
DYNAEXTERN(glTexParameteri); DYNAEXTERN(glTexParameteri);
DYNAEXTERN(glTexSubImage2D); DYNAEXTERN(glTexSubImage2D);
DYNAEXTERN(glVertex2i); DYNAEXTERN(glUseProgram);
DYNAEXTERN(glVertex3f); DYNAEXTERN(glVertexAttribPointer);
DYNAEXTERN(glVertex3fv);
DYNAEXTERN(glVertexPointer); DYNAEXTERN(glVertexPointer);
DYNAEXTERN(glViewport); DYNAEXTERN(glViewport);

View File

@ -0,0 +1,26 @@
#version 150 core
/*
* Descent 3
* Copyright (C) 2024 Descent Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
out vec4 out_color;
void main()
{
out_color = vec4(0);
}

View File

@ -0,0 +1,29 @@
#version 150 core
/*
* Descent 3
* Copyright (C) 2024 Descent Developers
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
in vec3 in_pos;
in vec4 in_color;
in vec2 in_uv0;
in vec2 in_uv1;
void main()
{
gl_Position = vec4(0);
}