This commit is contained in:
BENEDEK László 2024-10-12 14:31:15 +02:00
parent 17f8d58a67
commit 29e8eff82a
6 changed files with 136 additions and 27 deletions

4
.gitignore vendored
View File

@ -1 +1,3 @@
opengl-deferred
opengl-deferred
assets/textures
assets/geometries

View File

@ -5,7 +5,7 @@ layout (location = 1) in vec2 _tex;
layout (location = 2) in vec3 _norm;
uniform mat4 projection;
uniform mat4 camera;
uniform mat4 view;
uniform mat4 model;
out vec3 pos;
@ -13,7 +13,7 @@ out vec3 norm;
out vec2 tex;
void main() {
gl_Position = projection * camera * model * vec4(_pos, 1.0);
gl_Position = projection * view * model * vec4(_pos, 1.0);
pos = vec3(model * vec4(_pos, 1.0));
norm = _norm;
tex = _tex;

View File

@ -1,20 +1,65 @@
#version 460 core
uniform sampler2D albedo;
uniform sampler2D depth;
uniform sampler2D normal;
uniform sampler2D material;
uniform sampler2D position;
// gbuffer textures
uniform sampler2D s_albedo;
uniform sampler2D s_depth;
uniform sampler2D s_normal;
uniform sampler2D s_material;
uniform sampler2D s_position;
// lights
#define MAX_LIGHT_COUNT 100
#define POINT 0
#define SPOT 1
#define DIRECTIONAL 2
#define AMBIENT 3
struct light_t {
vec3 color;
vec3 position;
vec3 direction;
float intensity;
int type;
};
uniform light_t lights[MAX_LIGHT_COUNT];
uniform int light_count;
uniform vec3 view_pos;
// from vertex shader
in vec3 pos;
in vec2 tex;
out vec4 FragColor;
float map(float value, float min1, float max1, float min2, float max2) {
return min2 + (value - min1) * (max2 - min2) / (max1 - min1);
vec3 albedo;
float depth;
vec3 normal;
vec3 material; // specular, roughness, metalic
vec3 position;
vec3 calc_light(light_t light) {
vec3 light_dir = normalize(light.position - position);
vec3 view_dir = normalize(view_pos - position);
vec3 reflect_dir = reflect(-light_dir, normal);
float diffuse = max(dot(normal, light_dir), 0.0);
float specular = pow(max(dot(view_dir, reflect_dir), 0.0), 1 - material.y) * material.x;
return (diffuse + specular) * light.intensity * light.color / max(pow(length(light.position - position), 2), 1);
}
void main() {
FragColor = texture(position, tex);
albedo = texture(s_albedo, tex).rgb;
depth = texture(s_depth, tex).x;
normal = (texture(s_normal, tex).rgb * 2) - 1;
material = texture(s_material, tex).xyz;
position = texture(s_position, tex).xyz;
vec3 light_result;
for (int i = 0; i < light_count; i++) {
light_result += calc_light(lights[i]);
}
FragColor = vec4(albedo * light_result, 1);
}

42
main.go
View File

@ -7,6 +7,7 @@ import (
"git.tek.govt.hu/dowerx/opengl-deferred/types/gbuffer"
"git.tek.govt.hu/dowerx/opengl-deferred/types/geometry"
"git.tek.govt.hu/dowerx/opengl-deferred/types/light"
"git.tek.govt.hu/dowerx/opengl-deferred/types/shader"
"git.tek.govt.hu/dowerx/opengl-deferred/types/texture"
"github.com/go-gl/gl/v4.6-core/gl"
@ -15,8 +16,8 @@ import (
)
const (
WIDTH = 640
HEIGHT = 480
WIDTH = 800
HEIGHT = 600
TITLE = "opengl-deferred"
FOV = 45.0
)
@ -48,7 +49,7 @@ func main() {
}
gl.Enable(gl.DEPTH_TEST)
// gl.Enable(gl.CULL_FACE)
gl.Enable(gl.CULL_FACE)
gl.DepthFunc(gl.LESS)
gl.ClearColor(0, 0, 0, 0)
@ -87,7 +88,7 @@ func main() {
defer screenShader.Delete()
// geometry
cube, err := geometry.LoadOBJ("assets/geometries/suzanne.obj")
cube, err := geometry.LoadOBJ("assets/geometries/cube.obj")
if err != nil {
panic(err)
}
@ -130,6 +131,11 @@ func main() {
}
defer metalic.Delete()
// lights
lights := []light.Light{
{Color: [3]float32{1, 1, 1}, Position: mgl32.Vec3{3, 3, 3}, Intensity: 10, Type: light.POINT},
}
// gbuffer
gbuff, err := gbuffer.New(WIDTH, HEIGHT)
if err != nil {
@ -140,8 +146,8 @@ func main() {
// transformations
projection := mgl32.Perspective(mgl32.DegToRad(FOV), float32(WIDTH)/HEIGHT, 0.1, 10)
camera := mgl32.LookAtV(mgl32.Vec3{3, 3, 3}, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0})
model := mgl32.Ident4()
viewPositon := mgl32.Vec3{3, 3, 3}
view := mgl32.LookAtV(viewPositon, mgl32.Vec3{0, 0, 0}, mgl32.Vec3{0, 1, 0})
angle := 0.0
previousTime := glfw.GetTime()
@ -152,10 +158,12 @@ func main() {
previousTime = time
angle += elapsed
model = mgl32.HomogRotate3D(float32(angle), mgl32.Vec3{0, 1, 0})
model := mgl32.HomogRotate3D(float32(angle), mgl32.Vec3{0, 1, 0})
// first pass
// bind textures
gl.Enable(gl.DEPTH_TEST)
gbuff.Bind()
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
@ -169,7 +177,7 @@ func main() {
// transfer uniforms
deferredShader.Use()
deferredShader.Mat4("projection", projection)
deferredShader.Mat4("camera", camera)
deferredShader.Mat4("view", view)
deferredShader.Mat4("model", model)
deferredShader.Int("s_albedo", 0)
@ -180,17 +188,23 @@ func main() {
cube.Draw()
// second pass
gl.Disable(gl.DEPTH_TEST)
gl.BindFramebuffer(gl.FRAMEBUFFER, 0)
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.Clear(gl.COLOR_BUFFER_BIT)
gbuff.BindTextures()
screenShader.Use()
screenShader.Int("albedo", 0)
screenShader.Int("depth", 1)
screenShader.Int("normal", 2)
screenShader.Int("material", 3)
screenShader.Int("position", 4)
screenShader.Int("s_albedo", 0)
screenShader.Int("s_depth", 1)
screenShader.Int("s_normal", 2)
screenShader.Int("s_material", 3)
screenShader.Int("s_position", 4)
screenShader.Vec3("view_pos", &viewPositon[0])
for _, light := range lights {
screenShader.Light(&light)
}
screen.Draw()

20
types/light/light.go Normal file
View File

@ -0,0 +1,20 @@
package light
import "github.com/go-gl/mathgl/mgl32"
const MAX_LIGHT_COUNT = 100
const (
POINT int32 = iota
SPOT int32 = iota
DIRECTIONAL int32 = iota
AMBIENT int32 = iota
)
type Light struct {
Color mgl32.Vec3
Position mgl32.Vec3
Direction mgl32.Vec3
Intensity float32
Type int32
}

View File

@ -2,19 +2,23 @@ package shader
import (
"errors"
"fmt"
"strings"
"git.tek.govt.hu/dowerx/opengl-deferred/types/light"
"github.com/go-gl/gl/v4.6-core/gl"
"github.com/go-gl/mathgl/mgl32"
)
type Shader struct {
program uint32
uniforms map[string]int32
program uint32
uniforms map[string]int32
lightCount int32
}
func (s *Shader) Use() {
gl.UseProgram(s.program)
s.lightCount = 0
}
func (s *Shader) Delete() {
@ -40,6 +44,30 @@ func (s *Shader) Int(name string, val int32) {
gl.Uniform1i(s.getUniformLocation(name), val)
}
func (s *Shader) Float(name string, val float32) {
gl.Uniform1f(s.getUniformLocation(name), val)
}
func (s *Shader) Vec3(name string, val *float32) {
gl.Uniform3fv(s.getUniformLocation(name), 1, val)
}
func (s *Shader) Light(l *light.Light) error {
if s.lightCount >= light.MAX_LIGHT_COUNT {
return errors.New("too many lights")
}
s.Vec3(fmt.Sprintf("lights[%d].color", s.lightCount), &l.Color[0])
s.Vec3(fmt.Sprintf("lights[%d].position", s.lightCount), &l.Position[0])
s.Vec3(fmt.Sprintf("lights[%d].direction", s.lightCount), &l.Direction[0])
s.Float(fmt.Sprintf("lights[%d].intensity", s.lightCount), l.Intensity)
s.Int(fmt.Sprintf("lights[%d].type", s.lightCount), l.Type)
s.lightCount++
s.Int("light_count", s.lightCount)
return nil
}
func compileShader(source string, shaderType uint32) (uint32, error) {
shader := gl.CreateShader(shaderType)