Forum

Notifications
Clear all

Another OpenGL & AMD ROCm 3D Video Game Engine.

1 Posts
1 Users
0 Reactions
10 Views
 josh
(@josh)
Member Admin
Joined: 2 months ago
Posts: 510
Topic starter  

Here’s a comprehensive folder structure and source code outline for a 3D video game engine using OpenGL and AMD ROCm API calls:

## Folder Structure

“`
game_engine/
├── src/
│ ├── main.cpp
│ ├── engine/
│ │ ├── engine.cpp
│ │ └── engine.h
│ ├── graphics/
│ │ ├── renderer.cpp
│ │ ├── renderer.h
│ │ ├── shader.cpp
│ │ ├── shader.h
│ │ ├── mesh.cpp
│ │ ├── mesh.h
│ │ ├── texture.cpp
│ │ └── texture.h
│ ├── core/
│ │ ├── camera.cpp
│ │ ├── camera.h
│ │ ├── scene.cpp
│ │ └── scene.h
│ ├── systems/
│ │ ├── input_system.cpp
│ │ ├── input_system.h
│ │ ├── physics_system.cpp
│ │ └── physics_system.h
│ ├── utils/
│ │ ├── file_loader.cpp
│ │ └── file_loader.h
│ └── platforms/
│ ├── amd/
│ │ ├── rocm_context.cpp
│ │ ├── rocm_context.h
│ │ ├── compute_shader.cpp
│ │ └── compute_shader.h
│ └── opengl/
│ ├── opengl_context.cpp
│ ├── opengl_context.h
│ ├── buffer.cpp
│ └── buffer.h
├── assets/
│ ├── shaders/
│ │ ├── vertex.glsl
│ │ ├── fragment.glsl
│ │ └── compute.glsl
│ ├── models/
│ └── textures/
├── include/
│ ├── engine/
│ ├── graphics/
│ ├── core/
│ └── platforms/
├── CMakeLists.txt
└── README.md
“`

## Source Code Implementation

### src/main.cpp
“`cpp
#include “engine/engine.h”
#include <iostream>

int main() {
try {
Engine engine;
engine.initialize();
engine.run();
engine.cleanup();
} catch (const std::exception& e) {
std::cerr << “Error: ” << e.what() << std::endl;
return -1;
}

return 0;
}
“`

### src/engine/engine.h
“`cpp
#ifndef ENGINE_H
#define ENGINE_H

#include <memory>
#include <string>

class Renderer;
class InputSystem;
class PhysicsSystem;
class Scene;

class Engine {
public:
Engine();
~Engine();

void initialize();
void run();
void cleanup();

private:
std::unique_ptr<Renderer> renderer_;
std::unique_ptr<InputSystem> input_system_;
std::unique_ptr<PhysicsSystem> physics_system_;
std::unique_ptr<Scene> scene_;

bool is_running_;
};

#endif // ENGINE_H
“`

### src/engine/engine.cpp
“`cpp
#include “engine.h”
#include “../graphics/renderer.h”
#include “../systems/input_system.h”
#include “../systems/physics_system.h”
#include “../core/scene.h”
#include “../platforms/amd/rocm_context.h”
#include “../platforms/opengl/opengl_context.h”

Engine::Engine() : is_running_(false) {}

Engine::~Engine() = default;

void Engine::initialize() {
// Initialize OpenGL context
auto* gl_context = new OpenGLContext();
gl_context->initialize();

// Initialize ROCm context for compute shaders
auto* rocm_context = new ROCmContext();
rocm_context->initialize();

// Create systems
renderer_ = std::make_unique<Renderer>();
input_system_ = std::make_unique<InputSystem>();
physics_system_ = std::make_unique<PhysicsSystem>();
scene_ = std::make_unique<Scene>();

is_running_ = true;
}

void Engine::run() {
while (is_running_) {
// Handle input
input_system_->update();

// Update physics
physics_system_->update();

// Render scene
renderer_->render(*scene_);

// Swap buffers (OpenGL)
// This would be called from OpenGL context
}
}

void Engine::cleanup() {
is_running_ = false;
// Cleanup resources
}
“`

### src/platforms/amd/rocm_context.h
“`cpp
#ifndef ROCM_CONTEXT_H
#define ROCM_CONTEXT_H

#include <hip/hip_runtime.h>
#include <vector>

class ROCmContext {
public:
ROCmContext();
~ROCmContext();

bool initialize();
void cleanup();

// Compute shader management
hipError_t createComputeShader(const std::string& kernel_source,
const std::string& kernel_name,
hipModule_t* module);

hipError_t launchKernel(hipModule_t module,
const std::string& kernel_name,
void** args,
int num_args,
dim3 grid_size,
dim3 block_size);

private:
bool is_initialized_;
hipContext_t context_;
hipDevice_t device_;
};

#endif // ROCM_CONTEXT_H
“`

### src/platforms/amd/rocm_context.cpp
“`cpp
#include “rocm_context.h”
#include <iostream>
#include <fstream>
#include <sstream>

ROCmContext::ROCmContext() : is_initialized_(false), context_(nullptr), device_(0) {}

ROCmContext::~ROCmContext() {
cleanup();
}

bool ROCmContext::initialize() {
hipError_t error;

// Initialize HIP runtime
error = hipInit(0);
if (error != hipSuccess) {
std::cerr << “Failed to initialize HIP: ” << hipGetErrorString(error) << std::endl;
return false;
}

// Get device count
int device_count = 0;
error = hipGetDeviceCount(&device_count);
if (error != hipSuccess || device_count == 0) {
std::cerr << “No HIP devices found” << std::endl;
return false;
}

// Set device to use
error = hipSetDevice(0);
if (error != hipSuccess) {
std::cerr << “Failed to set HIP device: ” << hipGetErrorString(error) << std::endl;
return false;
}

// Get device properties
hipDeviceProp_t props;
error = hipGetDeviceProperties(&props, 0);
if (error != hipSuccess) {
std::cerr << “Failed to get device properties: ” << hipGetErrorString(error) << std::endl;
return false;
}

std::cout << “Using HIP device: ” << props.name << std::endl;

is_initialized_ = true;
return true;
}

void ROCmContext::cleanup() {
if (is_initialized_) {
hipDeviceSynchronize();
hipDeviceReset();
is_initialized_ = false;
}
}

hipError_t ROCmContext::createComputeShader(const std::string& kernel_source,
const std::string& kernel_name,
hipModule_t* module) {
if (!is_initialized_) return hipErrorNotInitialized;

// Compile the kernel source
hipError_t error = hipModuleLoadData(module, kernel_source.c_str());
if (error != hipSuccess) {
std::cerr << “Failed to load HIP module: ” << hipGetErrorString(error) << std::endl;
return error;
}

return hipSuccess;
}

hipError_t ROCmContext::launchKernel(hipModule_t module,
const std::string& kernel_name,
void** args,
int num_args,
dim3 grid_size,
dim3 block_size) {
if (!is_initialized_) return hipErrorNotInitialized;

hipFunction_t kernel;
hipError_t error = hipModuleGetFunction(&kernel, module, kernel_name.c_str());
if (error != hipSuccess) {
std::cerr << “Failed to get HIP function: ” << hipGetErrorString(error) << std::endl;
return error;
}

// Launch kernel
error = hipModuleLaunchKernel(kernel,
grid_size.x, grid_size.y, grid_size.z,
block_size.x, block_size.y, block_size.z,
0, // shared memory size
nullptr, // stream
args,
nullptr);

if (error != hipSuccess) {
std::cerr << “Failed to launch HIP kernel: ” << hipGetErrorString(error) << std::endl;
}

return error;
}
“`

### src/platforms/opengl/opengl_context.h
“`cpp
#ifndef OPENGL_CONTEXT_H
#define OPENGL_CONTEXT_H

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <string>

class OpenGLContext {
public:
OpenGLContext();
~OpenGLContext();

bool initialize(int width = 1920, int height = 1080);
void cleanup();
void swapBuffers();
void clearScreen(float r, float g, float b, float a = 1.0f);

GLFWwindow* getWindow() const { return window_; }

private:
GLFWwindow* window_;
int width_, height_;
};

#endif // OPENGL_CONTEXT_H
“`

### src/platforms/opengl/opengl_context.cpp
“`cpp
#include “opengl_context.h”
#include <iostream>

OpenGLContext::OpenGLContext() : window_(nullptr), width_(1920), height_(1080) {}

OpenGLContext::~OpenGLContext() {
cleanup();
}

bool OpenGLContext::initialize(int width, int height) {
width_ = width;
height_ = height;

// Initialize GLFW
if (!glfwInit()) {
std::cerr << “Failed to initialize GLFW” << std::endl;
return false;
}

// Configure GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 5);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

// Create window
window_ = glfwCreateWindow(width_, height_, “Game Engine”, nullptr, nullptr);
if (!window_) {
std::cerr << “Failed to create GLFW window” << std::endl;
cleanup();
return false;
}

glfwMakeContextCurrent(window_);

// Initialize GLEW
if (glewInit() != GLEW_OK) {
std::cerr << “Failed to initialize GLEW” << std::endl;
cleanup();
return false;
}

// Enable depth testing and face culling
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);

std::cout << “OpenGL initialized successfully” << std::endl;
return true;
}

void OpenGLContext::cleanup() {
if (window_) {
glfwDestroyWindow(window_);
window_ = nullptr;
}
glfwTerminate();
}

void OpenGLContext::swapBuffers() {
if (window_) {
glfwSwapBuffers(window_);
}
}

void OpenGLContext::clearScreen(float r, float g, float b, float a) {
glClearColor(r, g, b, a);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
“`

### src/graphics/renderer.h
“`cpp
#ifndef RENDERER_H
#define RENDERER_H

#include <memory>
#include <vector>
#include “../core/scene.h”

class Shader;
class Mesh;
class Texture;

class Renderer {
public:
Renderer();
~Renderer();

void render(const Scene& scene);

private:
void setupShaders();
void renderMesh(const Mesh& mesh, const Shader& shader);

std::vector<std::unique_ptr<Shader>> shaders_;
std::vector<std::unique_ptr<Mesh>> meshes_;
std::vector<std::unique_ptr<Texture>> textures_;
};

#endif // RENDERER_H
“`

### src/graphics/renderer.cpp
“`cpp
#include “renderer.h”
#include “shader.h”
#include “mesh.h”
#include “../core/scene.h”
#include “../platforms/opengl/opengl_context.h”

Renderer::Renderer() = default;

Renderer::~Renderer() = default;

void Renderer::render(const Scene& scene) {
// Clear screen
OpenGLContext* context = /* get current context */;
context->clearScreen(0.2f, 0.3f, 0.4f);

// Setup shaders
setupShaders();

// Render objects in scene
for (const auto& object : scene.getObjects()) {
if (object.mesh) {
renderMesh(*object.mesh, *shaders_[0]);
}
}
}

void Renderer::setupShaders() {
// Load and compile shaders
shaders_.clear();
shaders_.push_back(std::make_unique<Shader>(“assets/shaders/vertex.glsl”,
“assets/shaders/fragment.glsl”));
}

void Renderer::renderMesh(const Mesh& mesh, const Shader& shader) {
// Bind shader
shader.use();

// Set uniforms (model, view, projection matrices)
// This would be done through the OpenGL context

// Bind VAO and draw
glBindVertexArray(mesh.getVAO());
glDrawElements(GL_TRIANGLES, mesh.getIndexCount(), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
“`

### src/graphics/shader.h
“`cpp
#ifndef SHADER_H
#define SHADER_H

#include <string>
#include <unordered_map>
#include <GL/glew.h>

class Shader {
public:
Shader(const std::string& vertex_path, const std::string& fragment_path);
~Shader();

void use() const;
void setUniform(const std::string& name, int value) const;
void setUniform(const std::string& name, float value) const;
void setUniform(const std::string& name, const float* values, int count) const;

private:
GLuint program_;
GLuint vertex_shader_;
GLuint fragment_shader_;

bool compileShader(const std::string& path, GLenum type, GLuint* shader);
bool linkProgram();
};

#endif // SHADER_H
“`

### src/graphics/shader.cpp
“`cpp
#include “shader.h”
#include <iostream>
#include <fstream>
#include <sstream>

Shader::Shader(const std::string& vertex_path, const std::string& fragment_path) {
// Compile shaders
compileShader(vertex_path, GL_VERTEX_SHADER, &vertex_shader_);
compileShader(fragment_path, GL_FRAGMENT_SHADER, &fragment_shader_);

// Link program
linkProgram();
}

Shader::~Shader() {
glDeleteProgram(program_);
glDeleteShader(vertex_shader_);
glDeleteShader(fragment_shader_);
}

void Shader::use() const {
glUseProgram(program_);
}

void Shader::setUniform(const std::string& name, int value) const {
glUniform1i(glGetUniformLocation(program_, name.c_str()), value);
}

void Shader::setUniform(const std::string& name, float value) const {
glUniform1f(glGetUniformLocation(program_, name.c_str()), value);
}

void Shader::setUniform(const std::string& name, const float* values, int count) const {
glUniform1fv(glGetUniformLocation(program_, name.c_str()), count, values);
}

bool Shader::compileShader(const std::string& path, GLenum type, GLuint* shader) {
std::ifstream file(path);
if (!file.is_open()) {
std::cerr << “Failed to open shader file: ” << path << std::endl;
return false;
}

std::stringstream buffer;
buffer << file.rdbuf();
std::string source = buffer.str();

const char* src_ptr = source.c_str();
*shader = glCreateShader(type);
glShaderSource(*shader, 1, &src_ptr, nullptr);
glCompileShader(*shader);

// Check for compilation errors
GLint success;
glGetShaderiv(*shader, GL_COMPILE_STATUS, &success);
if (!success) {
char info_log[512];
glGetShaderInfoLog(*shader, 512, nullptr, info_log);
std::cerr << “Shader compilation error: ” << info_log << std::endl;
return false;
}

return true;
}

bool Shader::linkProgram() {
program_ = glCreateProgram();
glAttachShader(program_, vertex_shader_);
glAttachShader(program_, fragment_shader_);
glLinkProgram(program_);

// Check for linking errors
GLint success;
glGetProgramiv(program_, GL_LINK_STATUS, &success);
if (!success) {
char info_log[512];
glGetProgramInfoLog(program_, 512, nullptr, info_log);
std::cerr << “Shader program linking error: ” << info_log << std::endl;
return false;
}

return true;
}
“`

### assets/shaders/vertex.glsl
“`glsl
#version 450 core

layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoord;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec2 TexCoord;
out vec3 Normal;
out vec3 FragPos;

void main() {
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model)))) * aNormal;
TexCoord = aTexCoord;

gl_Position = projection * view * vec4(FragPos, 1.0);
}
“`

### assets/shaders/fragment.glsl
“`glsl
#version 450 core

in vec2 TexCoord;
in vec3 Normal;
in vec3 FragPos;

out vec4 FragColor;

uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform sampler2D diffuseTexture;

void main() {
// Ambient lighting
float ambientStrength = 0.1;
vec3 ambient = ambientStrength * lightColor;

// Diffuse lighting
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos – FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;

// Combine lighting
vec3 result = ambient + diffuse;
vec4 texColor = texture(diffuseTexture, TexCoord);

FragColor = vec4(result * texColor.rgb, texColor.a);
}
“`

### CMakeLists.txt (example)
“`cmake
cmake_minimum_required(VERSION 3.10)
project(GameEngine)

set(CMAKE_CXX_STANDARD 17)

# Find required packages
find_package(glfw3 REQUIRED)
find_package(GLEW REQUIRED)
find_package(OpenGL REQUIRED)

# Add executable
add_executable(${PROJECT_NAME}
src/main.cpp
src/graphics/shader.cpp
src/graphics/renderer.cpp
src/platforms/opengl/opengl_context.cpp
src/graphics/mesh.cpp
src/core/scene.cpp
)

# Link libraries
target_link_libraries(${PROJECT_NAME}
glfw
GLEW::GLEW
OpenGL::GL
)
“`

This implementation provides a basic framework for a 3D game engine that integrates OpenGL with AMD’s ROCm platform, using modern C++17 features and following good software engineering practices. The code is organized into logical modules with clear separation of concerns between rendering, shaders, graphics objects, and core systems.


   
Quote
Share: