Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
.*
!.gitignore
!.gitmodules
out
74 changes: 74 additions & 0 deletions resources/shader/demo.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#version 450

#define LIGHT_TYPE_DIRECTIONAL 0
#define LIGHT_TYPE_SPOT 1
#define LIGHT_TYPE_POINT 2

layout(location = 0) in vec2 uv_coord_frag;
layout(location = 1) in vec3 normal_vec_frag;
layout(location = 2) in vec3 render_position_frag;

layout(binding = 0) uniform sampler2D tx_color;
layout(binding = 1) uniform sampler2D tx_phong;// stores ambient/diffuse/specular/shinyness weights in r/g/b/a respectively

layout(location = 0) out vec4 out_color;

uniform vec3 camera_position;
uniform vec3 ambient_light;

// TODO figure out what to do about multiple light sources (ideally with variable length - "Shader Storage Buffer Objects" ? )
uniform int light_type;
uniform vec3 light_position;
uniform vec3 light_direction;
uniform float light_range;
uniform float light_spot_angle;
uniform vec3 light_color;
uniform float light_intensity;

void main()
{
vec4 texColor = texture(tx_color, uv_coord_frag);
vec4 phongData = texture(tx_phong, uv_coord_frag);
vec3 ambientColor = max(phongData.r * ambient_light, 0.0f);
vec3 diffuseColor;
vec3 specularColor;

// TODO light bounces? occlusion?
if (light_type == LIGHT_TYPE_DIRECTIONAL){
// direction, color, intensity

float diffuseDot = max(dot(-light_direction, normal_vec_frag), 0.0f);
float specularDot = max(dot(reflect(light_direction, normal_vec_frag), normalize(camera_position - render_position_frag)), 0.0f);
diffuseColor = phongData.g * diffuseDot * light_color * light_intensity;
specularColor = phongData.b * 8 * pow(specularDot, phongData.a * 255) * light_color * light_intensity;

} else if (light_type == LIGHT_TYPE_SPOT){
// position, direction, range, spot_angle, color, intensity
vec3 spotLightDirection = normalize(render_position_frag - light_position);
// here we're (ab-)using the fact that the dot product of two normalized vectors is the cosine of their angle
float spotLightAngle = dot(light_direction, spotLightDirection);
float spotLightDistance = length(render_position_frag - light_position);
if (spotLightAngle > light_spot_angle && spotLightDistance <= light_range){
float distanceFactor = 0.01f / pow(spotLightDistance / light_range, 2);
float diffuseDot = max(dot(-spotLightDirection, normal_vec_frag), 0.0f);
float specularDot = max(dot(reflect(spotLightDirection, normal_vec_frag), normalize(camera_position - render_position_frag)), 0.0f);
diffuseColor = phongData.g * diffuseDot * light_color * light_intensity * distanceFactor;
specularColor = phongData.b * 8 * pow(specularDot, phongData.a * 255) * light_color * light_intensity * distanceFactor;
}

} else if (light_type == LIGHT_TYPE_POINT){
// position, range, color, intensity
// light intensity should diminish proportionally to `1 / distance_squared`
vec3 pointLightDirection = normalize(render_position_frag - light_position);
float pointLightDistance = length(render_position_frag - light_position);
if (pointLightDistance <= light_range){
float distanceFactor = 0.01f / pow(pointLightDistance / light_range, 2);
float diffuseDot = max(dot(-pointLightDirection, normal_vec_frag), 0.0f);
float specularDot = max(dot(reflect(pointLightDirection, normal_vec_frag), normalize(camera_position - render_position_frag)), 0.0f);
diffuseColor = phongData.g * diffuseDot * light_color * light_intensity * distanceFactor;
specularColor = phongData.b * 8 * pow(specularDot, phongData.a * 255) * light_color * light_intensity * distanceFactor;
}
}

out_color = texColor * vec4(ambientColor + diffuseColor + specularColor, 1.0f);
}
22 changes: 22 additions & 0 deletions resources/shader/demo.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#version 450

layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 uv_coord;
layout(location = 2) in vec3 normal_vec;

layout(location = 0) out vec2 uv_coord_frag;
layout(location = 1) out vec3 normal_vec_frag;
layout(location = 2) out vec3 render_position_frag;

uniform mat4 object_to_world_matrix;
uniform mat4 world_to_camera_matrix;

void main()
{
vec4 worldPosition = object_to_world_matrix * vec4(in_position, 1.0f);
gl_Position = world_to_camera_matrix * worldPosition;
render_position_frag = worldPosition.xyz;

uv_coord_frag = uv_coord;
normal_vec_frag = normal_vec;
}
Binary file added resources/textures/Planet1_phong.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
155 changes: 121 additions & 34 deletions src/engine/graphics/camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,125 @@

namespace graphics {

using namespace glm;

Camera::Camera(float _fov, float _zNear, float zFar)
: m_projection(glm::perspective(glm::radians(_fov), Device::getAspectRatio(), _zNear, zFar)),
m_view(glm::identity<glm::mat4>())
{
updateMatrices();
}

Camera::Camera(glm::vec2 _size, glm::vec2 _origin, float _zNear, float _zFar)
: m_projection(glm::ortho(-_size.x*_origin.x, _size.x*(1.f-_origin.x),
-_size.y * _origin.y, _size.y* (1.f - _origin.y),
_zNear, _zFar)),
m_view(glm::identity<glm::mat4>())
{
updateMatrices();
}

vec3 Camera::toWorldSpace(const vec2& _screenSpace) const
{
vec2 clipSpace = _screenSpace / vec2(Device::getBufferSize());
clipSpace.y = 1.f - clipSpace.y;
clipSpace = clipSpace * 2.f - vec2(1.f, 1.f);

const vec4 worldSpace = m_viewProjectionInv * vec4(clipSpace, -1.f, 1.f);

return vec3(worldSpace) / worldSpace.w;
}

void Camera::updateMatrices()
{
m_viewProjection = m_projection * m_view;
m_viewProjectionInv = glm::inverse(m_viewProjection);
}
using namespace glm;
constexpr glm::vec3 RIGHT_VECTOR = glm::vec3(1.0f, 0.0f, 0.0f);
constexpr glm::vec3 UP_VECTOR = glm::vec3(0.0f, 1.0f, 0.0f);
constexpr glm::vec3 FORWARD_VECTOR = glm::vec3(0.0f, 0.0f, 1.0f);

Camera::Camera(float _fov, float _zNear, float zFar)
: m_projection(glm::perspective(glm::radians(_fov), Device::getAspectRatio(), _zNear, zFar)),
m_view(glm::identity<glm::mat4>()) {
updateMatrices();
}

Camera::Camera(glm::vec2 _size, glm::vec2 _origin, float _zNear, float _zFar)
: m_projection(glm::ortho(-_size.x * _origin.x, _size.x * (1.f - _origin.x),
-_size.y * _origin.y, _size.y * (1.f - _origin.y),
_zNear, _zFar)),
m_view(glm::identity<glm::mat4>()) {
updateMatrices();
}

vec3 Camera::toWorldSpace(const vec2 &_screenSpace) const {
vec2 clipSpace = _screenSpace / vec2(Device::getBufferSize());
clipSpace.y = 1.f - clipSpace.y;
clipSpace = clipSpace * 2.f - vec2(1.f, 1.f);

const vec4 worldSpace = m_viewProjectionInv * vec4(clipSpace, -1.f, 1.f);

return vec3(worldSpace) / worldSpace.w;
}

void Camera::updateMatrices() {
m_viewProjection = m_projection * m_view;
m_viewProjectionInv = glm::inverse(m_viewProjection);
updateTransform();
}

void Camera::updateTransform() {
lookAtMatrix = glm::lookAt(cameraPosition, cameraPosition + cameraForward, cameraUp);
// fix x direction (gets inverted due to RHS / cross product)
lookAtMatrix[0][0] *= -1.0f;
lookAtMatrix[1][0] *= -1.0f;
lookAtMatrix[2][0] *= -1.0f;
lookAtMatrix[3][0] *= -1.0f;
worldToCameraMatrix = m_viewProjection * lookAtMatrix;
}

void Camera::moveRelative(const float &right, const float &up, const float &forward) {
if (right == 0.0f && up == 0.0f && forward == 0.0f) {
return;
}

if (right != 0.0f) {
cameraPosition += cameraRight * right;
}
if (up != 0.0f) {
cameraPosition += cameraUp * up;
}
if (forward != 0.0f) {
cameraPosition += cameraForward * forward;
}
updateTransform();
}

void Camera::moveAbsolute(const vec3 &direction) {
cameraPosition += direction;
updateTransform();
}

void Camera::setRotation(const float &yawAngle, const float &pitchAngle, const float &rollAngle) {
cameraRight = RIGHT_VECTOR;
cameraUp = UP_VECTOR;
cameraForward = FORWARD_VECTOR;
rotate(yawAngle, pitchAngle, rollAngle);
}

void Camera::setRotation(const glm::mat3 &rotationMatrix) {
cameraRight = rotationMatrix * RIGHT_VECTOR;
cameraUp = rotationMatrix * UP_VECTOR;
cameraForward = rotationMatrix * FORWARD_VECTOR;
updateTransform();
}

void Camera::rotate(const float &yawAngle, const float &pitchAngle, const float &rollAngle) {
if (yawAngle == 0.0f && pitchAngle == 0.0f && rollAngle == 0.0f) {
return;
}

if (yawAngle != 0.0f) {
auto yawRotationMatrix = glm::mat3(glm::rotate(
glm::identity<glm::mat4>(),
glm::radians(yawAngle),
cameraUp));
cameraRight = yawRotationMatrix * cameraRight;
cameraForward = yawRotationMatrix * cameraForward;
}
if (pitchAngle != 0.0f) {
auto pitchRotationMatrix = glm::mat3(glm::rotate(
glm::identity<glm::mat4>(),
glm::radians(pitchAngle),
cameraRight));
cameraForward = pitchRotationMatrix * cameraForward;
cameraUp = pitchRotationMatrix * cameraUp;
}
if (rollAngle != 0.0f) {
auto rollRotationMatrix = glm::mat3(glm::rotate(
glm::identity<glm::mat4>(),
glm::radians(rollAngle),
cameraForward));
cameraRight = rollRotationMatrix * cameraRight;
cameraUp = rollRotationMatrix * cameraUp;
}

updateTransform();
}

void Camera::rotate(const mat3 &rotationMatrix) {
cameraRight = rotationMatrix * cameraRight;
cameraUp = rotationMatrix * cameraUp;
cameraForward = rotationMatrix * cameraForward;
updateTransform();
}

}
97 changes: 72 additions & 25 deletions src/engine/graphics/camera.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,76 @@

namespace graphics {

class Camera
{
public:
// Perspective
// @param _fov as angle
Camera(float _fov, float _zNear, float zFar);
// Orthogonal
Camera(glm::vec2 _size, glm::vec2 _origin = glm::vec2(0.f), float _zNear = 0.f, float _zFar = 1.f);

const glm::mat4& getView() const { return m_view; }
const glm::mat4& getProjection() const { return m_projection; }
const glm::mat4& getViewProjection() const { return m_viewProjection; }

void setView(const glm::mat4& _view) { m_view = _view; updateMatrices(); }

// @Return the position of the point _screenSpace on the near plane of this camera
glm::vec3 toWorldSpace(const glm::vec2& _sceenSpace) const;
private:
void updateMatrices();

glm::mat4 m_projection;
glm::mat4 m_view;
glm::mat4 m_viewProjection;
glm::mat4 m_viewProjectionInv;
};
class Camera {
public:
// Perspective
// @param _fov as angle
Camera(float _fov, float _zNear, float zFar);

// Orthogonal
Camera(glm::vec2 _size, glm::vec2 _origin = glm::vec2(0.f), float _zNear = 0.f, float _zFar = 1.f);

[[nodiscard]] const glm::mat4 &getView() const { return m_view; }

[[nodiscard]] const glm::mat4 &getProjection() const { return m_projection; }

[[nodiscard]] const glm::mat4 &getViewProjection() const { return m_viewProjection; }

void setView(const glm::mat4 &_view) {
m_view = _view;
updateMatrices();
}

// @Return the position of the point _screenSpace on the near plane of this camera
[[nodiscard]] glm::vec3 toWorldSpace(const glm::vec2 &_screenSpace) const;

[[nodiscard]] const glm::vec3 &getPosition() const { return cameraPosition; }

void setPosition(const glm::vec3 &position) {
cameraPosition = position;
updateTransform();
}

void moveRelative(const float &right, const float &up, const float &forward);

void moveAbsolute(const glm::vec3 &direction);

[[nodiscard]] const glm::vec3 &forwardVector() const { return cameraForward; }

[[nodiscard]] const glm::vec3 &upVector() const { return cameraUp; }

[[nodiscard]] const glm::vec3 &rightVector() const { return cameraRight; }

// sets the camera rotation
void setRotation(const float &yawAngle, const float &pitchAngle, const float &rollAngle);

// sets the camera rotation
void setRotation(const glm::mat3 &rotationMatrix);

// rotates the camera based on its current rotation
void rotate(const float &yawAngle, const float &pitchAngle, const float &rollAngle);

// rotates the camera based on its current rotation
void rotate(const glm::mat3 &rotationMatrix);

[[nodiscard]] const glm::mat4 &getWorldToCamera() const { return worldToCameraMatrix; }

private:
void updateMatrices();

void updateTransform();

glm::mat4 m_projection;
glm::mat4 m_view;
glm::mat4 m_viewProjection;
glm::mat4 m_viewProjectionInv;

glm::vec3 cameraPosition = {0.0f, 0.0f, 0.0f};
glm::vec3 cameraForward = {0.0f, 0.0f, 1.0f};
glm::vec3 cameraUp = {0.0f, 1.0f, 0.0f};
glm::vec3 cameraRight = {1.0f, 0.0f, 0.0f};
glm::mat4 lookAtMatrix;

glm::mat4 worldToCameraMatrix;
};
}
10 changes: 6 additions & 4 deletions src/engine/graphics/core/geometrybuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ namespace graphics {
m_indexSize(_indexed),
m_vertexCount(0),
m_indexCount(0),
m_instanceCount(0)
m_instanceCount(0),
m_vao(0),
m_vbo(0)
{
// Analyze vertex data (vertexsize, instancesize)
for(int i = 0; i < _numAttributes; ++i)
Expand Down Expand Up @@ -80,13 +82,13 @@ namespace graphics {
glCall(glBufferData, GL_ARRAY_BUFFER, m_instanceCapacity, nullptr, GL_STATIC_DRAW);

// Bind Attributes
unsigned offset = 0;
unsigned offset2 = 0;
for(int i = 0; i < _numAttributes; ++i) if(_attributes[i].perInstance)
{
// Also set this attribute to be instanced
glCall(glVertexAttribDivisor, attribIndex, 1);
enableAttribute(attribIndex++, _attributes[i], m_instanceVertexSize, offset);
offset += attributeSize(_attributes[i]);
enableAttribute(attribIndex++, _attributes[i], m_instanceVertexSize, offset2);
offset2 += attributeSize(_attributes[i]);
}
}

Expand Down
Loading