normal mapping, basic pbr
This commit is contained in:
parent
92b9e651ac
commit
0497ff9ac7
@ -9,6 +9,7 @@ uniform sampler2D s_metalic;
|
|||||||
in vec3 pos;
|
in vec3 pos;
|
||||||
in vec3 norm;
|
in vec3 norm;
|
||||||
in vec2 tex;
|
in vec2 tex;
|
||||||
|
in mat3 TBN;
|
||||||
|
|
||||||
layout (location = 0) out vec3 albedo;
|
layout (location = 0) out vec3 albedo;
|
||||||
layout (location = 1) out vec3 normal;
|
layout (location = 1) out vec3 normal;
|
||||||
@ -16,10 +17,10 @@ layout (location = 2) out vec3 material;
|
|||||||
layout (location = 3) out vec3 position;
|
layout (location = 3) out vec3 position;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
position = pos;
|
|
||||||
albedo = texture(s_albedo, tex).rgb;
|
albedo = texture(s_albedo, tex).rgb;
|
||||||
normal = normalize(texture(s_normal, tex).rgb * 2.0 - 1.0);
|
normal = normalize(TBN * (texture(s_normal, tex).rgb * 2.0 - 1.0));
|
||||||
material.x = texture(s_specular, tex).x;
|
material.x = texture(s_specular, tex).x;
|
||||||
material.y = texture(s_roughness, tex).y;
|
material.y = texture(s_roughness, tex).y;
|
||||||
material.z = texture(s_metalic, tex).z;
|
material.z = texture(s_metalic, tex).z;
|
||||||
|
position = pos;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
layout (location = 0) in vec3 _pos;
|
layout (location = 0) in vec3 _pos;
|
||||||
layout (location = 1) in vec2 _tex;
|
layout (location = 1) in vec2 _tex;
|
||||||
layout (location = 2) in vec3 _norm;
|
layout (location = 2) in vec3 _norm;
|
||||||
|
layout (location = 3) in vec3 _tan;
|
||||||
|
|
||||||
uniform mat4 projection;
|
uniform mat4 projection;
|
||||||
uniform mat4 view;
|
uniform mat4 view;
|
||||||
@ -11,8 +12,14 @@ uniform mat4 model;
|
|||||||
out vec3 pos;
|
out vec3 pos;
|
||||||
out vec3 norm;
|
out vec3 norm;
|
||||||
out vec2 tex;
|
out vec2 tex;
|
||||||
|
out mat3 TBN;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
vec3 T = normalize(vec3(model * vec4(_tan, 0)));
|
||||||
|
vec3 N = normalize(vec3(model * vec4(_norm, 0)));
|
||||||
|
vec3 B = cross(N, T);
|
||||||
|
TBN = mat3(T, B, N);
|
||||||
|
|
||||||
gl_Position = projection * view * model * vec4(_pos, 1.0);
|
gl_Position = projection * view * model * vec4(_pos, 1.0);
|
||||||
pos = vec3(model * vec4(_pos, 1.0));
|
pos = vec3(model * vec4(_pos, 1.0));
|
||||||
norm = mat3(transpose(inverse(model))) * _norm;
|
norm = mat3(transpose(inverse(model))) * _norm;
|
||||||
|
151
assets/shader/pbr/pbr.fs
Normal file
151
assets/shader/pbr/pbr.fs
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#version 460 core
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
vec3 albedo;
|
||||||
|
float depth;
|
||||||
|
vec3 normal;
|
||||||
|
vec3 material; // specular, roughness, metalic
|
||||||
|
vec3 position;
|
||||||
|
|
||||||
|
// float specular;
|
||||||
|
float roughness;
|
||||||
|
float metalic;
|
||||||
|
|
||||||
|
const float PI = 3.14159265359;
|
||||||
|
|
||||||
|
float DistributionGGX(vec3 N, vec3 H, float roughness)
|
||||||
|
{
|
||||||
|
float a = roughness*roughness;
|
||||||
|
float a2 = a*a;
|
||||||
|
float NdotH = max(dot(N, H), 0.0);
|
||||||
|
float NdotH2 = NdotH*NdotH;
|
||||||
|
|
||||||
|
float nom = a2;
|
||||||
|
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
|
||||||
|
denom = PI * denom * denom;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
float r = (roughness + 1.0);
|
||||||
|
float k = (r*r) / 8.0;
|
||||||
|
|
||||||
|
float nom = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||||
|
{
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 fresnelSchlick(float cosTheta, vec3 F0)
|
||||||
|
{
|
||||||
|
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
albedo = pow(texture(s_albedo, tex).rgb, vec3(2.2));
|
||||||
|
depth = texture(s_depth, tex).x;
|
||||||
|
normal = normalize(texture(s_normal, tex).rgb);
|
||||||
|
material = texture(s_material, tex).xyz;
|
||||||
|
{
|
||||||
|
// specular = material.x;
|
||||||
|
roughness = 1 - material.y;
|
||||||
|
metalic = material.z;
|
||||||
|
// metalic = 0;
|
||||||
|
}
|
||||||
|
position = texture(s_position, tex).xyz;
|
||||||
|
|
||||||
|
vec3 N = normal;
|
||||||
|
vec3 V = normalize(view_pos - position);
|
||||||
|
|
||||||
|
vec3 F0 = vec3(0.04);
|
||||||
|
F0 = mix(F0, albedo, metalic);
|
||||||
|
|
||||||
|
vec3 Lo = vec3(0.0);
|
||||||
|
for(int i = 0; i < light_count; i++)
|
||||||
|
{
|
||||||
|
// calculate per-light radiance
|
||||||
|
vec3 L = normalize(lights[i].position - position);
|
||||||
|
vec3 H = normalize(V + L);
|
||||||
|
float distance = length(lights[i].position - position);
|
||||||
|
float attenuation = 1.0 / (distance * distance);
|
||||||
|
vec3 radiance = lights[i].color * lights[i].intensity * attenuation;
|
||||||
|
|
||||||
|
// Cook-Torrance BRDF
|
||||||
|
float NDF = DistributionGGX(N, H, roughness);
|
||||||
|
float G = GeometrySmith(N, V, L, roughness);
|
||||||
|
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
|
||||||
|
|
||||||
|
vec3 numerator = NDF * G * F;
|
||||||
|
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; // + 0.0001 to prevent divide by zero
|
||||||
|
vec3 specular = numerator / denominator;
|
||||||
|
|
||||||
|
// kS is equal to Fresnel
|
||||||
|
vec3 kS = F;
|
||||||
|
// for energy conservation, the diffuse and specular light can't
|
||||||
|
// be above 1.0 (unless the surface emits light); to preserve this
|
||||||
|
// relationship the diffuse component (kD) should equal 1.0 - kS.
|
||||||
|
vec3 kD = vec3(1.0) - kS;
|
||||||
|
// multiply kD by the inverse metalness such that only non-metals
|
||||||
|
// have diffuse lighting, or a linear blend if partly metal (pure metals
|
||||||
|
// have no diffuse light).
|
||||||
|
kD *= 1.0 - metalic;
|
||||||
|
|
||||||
|
// scale light by NdotL
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
|
||||||
|
// add to outgoing radiance Lo
|
||||||
|
Lo += (kD * albedo / PI + specular) * radiance * NdotL; // note that we already multiplied the BRDF by the Fresnel (kS) so we won't multiply by kS again
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ambient = vec3(0.03) * albedo * 1.0;
|
||||||
|
vec3 color = ambient + Lo;
|
||||||
|
|
||||||
|
color = color / (color + vec3(1.0));
|
||||||
|
color = pow(color, vec3(1.0/2.2));
|
||||||
|
|
||||||
|
FragColor = vec4(color, 1.0);
|
||||||
|
}
|
13
assets/shader/pbr/pbr.vs
Normal file
13
assets/shader/pbr/pbr.vs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#version 460 core
|
||||||
|
|
||||||
|
layout (location = 0) in vec3 _pos;
|
||||||
|
layout (location = 1) in vec2 _tex;
|
||||||
|
|
||||||
|
out vec3 pos;
|
||||||
|
out vec2 tex;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
gl_Position = vec4(_pos.xy, 0, 1);
|
||||||
|
pos = _pos;
|
||||||
|
tex = _tex;
|
||||||
|
}
|
63
assets/shader/screen/screen-debug.fs
Normal file
63
assets/shader/screen/screen-debug.fs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#version 460 core
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
vec3 albedo;
|
||||||
|
float depth;
|
||||||
|
vec3 normal;
|
||||||
|
vec3 material; // specular, roughness, metalic
|
||||||
|
vec3 position;
|
||||||
|
|
||||||
|
float specular;
|
||||||
|
float roughness;
|
||||||
|
float metalic;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
// albedo, normal
|
||||||
|
// material, position
|
||||||
|
albedo = texture(s_albedo, tex*2).rgb;
|
||||||
|
depth = texture(s_depth, tex*2).x;
|
||||||
|
normal = normalize(texture(s_normal, tex*2).rgb);
|
||||||
|
material = texture(s_material, tex*2).xyz;
|
||||||
|
{
|
||||||
|
specular = material.x;
|
||||||
|
roughness = material.y;
|
||||||
|
metalic = material.z;
|
||||||
|
}
|
||||||
|
position = texture(s_position, tex*2).xyz;
|
||||||
|
|
||||||
|
FragColor = vec4(
|
||||||
|
(pos.x < 0 ? (pos.y < 0 ? material : albedo) : (pos.y < 0 ? position : normal)),
|
||||||
|
1);
|
||||||
|
}
|
@ -38,35 +38,46 @@ float depth;
|
|||||||
vec3 normal;
|
vec3 normal;
|
||||||
vec3 material; // specular, roughness, metalic
|
vec3 material; // specular, roughness, metalic
|
||||||
vec3 position;
|
vec3 position;
|
||||||
|
vec2 texture_coords;
|
||||||
|
|
||||||
float specular;
|
float specular;
|
||||||
float roughness;
|
float roughness;
|
||||||
float metalic;
|
float metalic;
|
||||||
|
|
||||||
vec3 calc_light(light_t light) {
|
vec3 calc_light(light_t light) {
|
||||||
|
// diffuse
|
||||||
vec3 light_dir = normalize(light.position - position);
|
vec3 light_dir = normalize(light.position - position);
|
||||||
|
float diff = max(dot(normal, light_dir), 0);
|
||||||
|
vec3 diffuse_light = diff * light.color * light.intensity;
|
||||||
|
|
||||||
|
// specular
|
||||||
|
float specular_strength = 0.5;
|
||||||
vec3 view_dir = normalize(view_pos - position);
|
vec3 view_dir = normalize(view_pos - position);
|
||||||
vec3 reflect_dir = reflect(-light_dir, normal);
|
vec3 reflect_dir = reflect(-light_dir, normal);
|
||||||
|
|
||||||
float diffuse = max(dot(normal, light_dir), 0.0);
|
float spec = pow(max(dot(view_dir, reflect_dir), 0), 32);
|
||||||
float specular = pow(max(dot(view_dir, reflect_dir), 0.0), 1 - roughness) * specular;
|
vec3 specular_light = specular_strength * spec * light.color * light.intensity * specular;
|
||||||
|
|
||||||
return (diffuse + specular) * light.intensity * light.color / max(pow(length(light.position - position), 2), 1);
|
// attenuation
|
||||||
|
float dist = length(light.position - position);
|
||||||
|
float attenuation = 1 / max(pow(dist, 2), 1);
|
||||||
|
|
||||||
|
return (diffuse_light + specular_light) * attenuation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
albedo = texture(s_albedo, tex).rgb;
|
albedo = pow(texture(s_albedo, tex).rgb, vec3(2.2));
|
||||||
depth = texture(s_depth, tex).x;
|
depth = texture(s_depth, tex).x;
|
||||||
normal = texture(s_normal, tex).rgb;
|
normal = normalize(texture(s_normal, tex).rgb);
|
||||||
material = texture(s_material, tex).xyz;
|
material = texture(s_material, tex).xyz;
|
||||||
{
|
{
|
||||||
specular = material.x;
|
specular = material.x;
|
||||||
roughness = material.y;
|
roughness = 1 - material.y;
|
||||||
metalic = material.z;
|
metalic = material.z;
|
||||||
}
|
}
|
||||||
position = texture(s_position, tex).xyz;
|
position = texture(s_position, tex).xyz;
|
||||||
|
|
||||||
vec3 light_result;
|
vec3 light_result = vec3(0.1);
|
||||||
for (int i = 0; i < light_count; i++) {
|
for (int i = 0; i < light_count; i++) {
|
||||||
light_result += calc_light(lights[i]);
|
light_result += calc_light(lights[i]);
|
||||||
}
|
}
|
||||||
|
26
main.go
26
main.go
@ -73,11 +73,13 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer deferredShader.Delete()
|
defer deferredShader.Delete()
|
||||||
|
|
||||||
vertexSource, err = os.ReadFile("assets/shader/screen/screen.vs")
|
vertexSource, err = os.ReadFile("assets/shader/pbr/pbr.vs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
fragmentSource, err = os.ReadFile("assets/shader/screen/screen.fs")
|
// fragmentSource, err = os.ReadFile("assets/shader/screen/screen-debug.fs")
|
||||||
|
// fragmentSource, err = os.ReadFile("assets/shader/screen/screen.fs")
|
||||||
|
fragmentSource, err = os.ReadFile("assets/shader/pbr/pbr.fs")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -144,10 +146,23 @@ func main() {
|
|||||||
}
|
}
|
||||||
defer metalic.Delete()
|
defer metalic.Delete()
|
||||||
|
|
||||||
|
white, err := texture.Load("assets/textures/white.png")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer white.Delete()
|
||||||
|
|
||||||
|
black, err := texture.Load("assets/textures/black.png")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer black.Delete()
|
||||||
|
|
||||||
// lights
|
// lights
|
||||||
lights := []light.Light{
|
lights := []light.Light{
|
||||||
{Color: [3]float32{0, 1, 0}, Position: mgl32.Vec3{3, 3, 3}, Intensity: 15, Type: light.POINT},
|
{Color: [3]float32{1, 1, 1}, Position: mgl32.Vec3{0, 10, 0}, Intensity: 40, Type: light.POINT},
|
||||||
{Color: [3]float32{1, 0, 1}, Position: mgl32.Vec3{3, 3, -3}, Intensity: 15, Type: light.POINT},
|
{Color: [3]float32{1, 0, 0}, Position: mgl32.Vec3{5, 5, 5}, Intensity: 30, Type: light.POINT},
|
||||||
|
{Color: [3]float32{0, 0, 1}, Position: mgl32.Vec3{-5, 5, -5}, Intensity: 30, Type: light.POINT},
|
||||||
}
|
}
|
||||||
|
|
||||||
// gbuffer
|
// gbuffer
|
||||||
@ -161,14 +176,13 @@ func main() {
|
|||||||
// transformations
|
// transformations
|
||||||
projection := mgl32.Perspective(mgl32.DegToRad(FOV), float32(WIDTH)/HEIGHT, 0.1, 1000)
|
projection := mgl32.Perspective(mgl32.DegToRad(FOV), float32(WIDTH)/HEIGHT, 0.1, 1000)
|
||||||
model := mgl32.Ident4()
|
model := mgl32.Ident4()
|
||||||
controls := fpscontrols.Get(10, 10, mgl32.Vec3{0, 0, -10}, mgl32.Vec2{0, 0}, window)
|
controls := fpscontrols.Get(15, 10, mgl32.Vec3{0, 0, -10}, mgl32.Vec2{0, 0}, window)
|
||||||
|
|
||||||
for !window.ShouldClose() {
|
for !window.ShouldClose() {
|
||||||
glfw.PollEvents()
|
glfw.PollEvents()
|
||||||
controls.Update()
|
controls.Update()
|
||||||
|
|
||||||
// first pass
|
// first pass
|
||||||
// bind textures
|
|
||||||
gl.Enable(gl.DEPTH_TEST)
|
gl.Enable(gl.DEPTH_TEST)
|
||||||
|
|
||||||
gbuff.Bind()
|
gbuff.Bind()
|
||||||
|
@ -12,7 +12,7 @@ type GBuffer struct {
|
|||||||
colorAttachments [4]uint32 // albedo, normal, material, position
|
colorAttachments [4]uint32 // albedo, normal, material, position
|
||||||
}
|
}
|
||||||
|
|
||||||
var attachments = []uint32{
|
var attachments = [...]uint32{
|
||||||
gl.COLOR_ATTACHMENT0,
|
gl.COLOR_ATTACHMENT0,
|
||||||
gl.COLOR_ATTACHMENT1,
|
gl.COLOR_ATTACHMENT1,
|
||||||
gl.COLOR_ATTACHMENT2,
|
gl.COLOR_ATTACHMENT2,
|
||||||
@ -25,18 +25,23 @@ func (b *GBuffer) Bind() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *GBuffer) BindTextures() {
|
func (b *GBuffer) BindTextures() {
|
||||||
|
// albedo
|
||||||
gl.ActiveTexture(gl.TEXTURE0)
|
gl.ActiveTexture(gl.TEXTURE0)
|
||||||
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[0])
|
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[0])
|
||||||
|
|
||||||
|
// depth
|
||||||
gl.ActiveTexture(gl.TEXTURE1)
|
gl.ActiveTexture(gl.TEXTURE1)
|
||||||
gl.BindTexture(gl.TEXTURE_2D, b.depth)
|
gl.BindTexture(gl.TEXTURE_2D, b.depth)
|
||||||
|
|
||||||
|
// normal
|
||||||
gl.ActiveTexture(gl.TEXTURE2)
|
gl.ActiveTexture(gl.TEXTURE2)
|
||||||
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[1])
|
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[1])
|
||||||
|
|
||||||
|
// material
|
||||||
gl.ActiveTexture(gl.TEXTURE3)
|
gl.ActiveTexture(gl.TEXTURE3)
|
||||||
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[2])
|
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[2])
|
||||||
|
|
||||||
|
// position
|
||||||
gl.ActiveTexture(gl.TEXTURE4)
|
gl.ActiveTexture(gl.TEXTURE4)
|
||||||
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[3])
|
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[3])
|
||||||
}
|
}
|
||||||
@ -54,14 +59,17 @@ func New(width int, height int) (buffer GBuffer, _ error) {
|
|||||||
gl.GenFramebuffers(1, &buffer.framebuffer)
|
gl.GenFramebuffers(1, &buffer.framebuffer)
|
||||||
gl.BindFramebuffer(gl.FRAMEBUFFER, buffer.framebuffer)
|
gl.BindFramebuffer(gl.FRAMEBUFFER, buffer.framebuffer)
|
||||||
|
|
||||||
|
var i uint32 = 0
|
||||||
|
|
||||||
// albedo
|
// albedo
|
||||||
gl.GenTextures(1, &buffer.colorAttachments[0])
|
gl.GenTextures(1, &buffer.colorAttachments[i])
|
||||||
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[0])
|
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[i])
|
||||||
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(width), int32(height), 0, gl.RGB, gl.UNSIGNED_BYTE, nil)
|
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(width), int32(height), 0, gl.RGB, gl.FLOAT, nil)
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||||
gl.BindTexture(gl.TEXTURE_2D, 0)
|
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||||
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, buffer.colorAttachments[0], 0)
|
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i, gl.TEXTURE_2D, buffer.colorAttachments[i], 0)
|
||||||
|
i++
|
||||||
|
|
||||||
// depth
|
// depth
|
||||||
gl.GenTextures(1, &buffer.depth)
|
gl.GenTextures(1, &buffer.depth)
|
||||||
@ -73,31 +81,34 @@ func New(width int, height int) (buffer GBuffer, _ error) {
|
|||||||
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, buffer.depth, 0)
|
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, buffer.depth, 0)
|
||||||
|
|
||||||
// normal
|
// normal
|
||||||
gl.GenTextures(1, &buffer.colorAttachments[1])
|
gl.GenTextures(1, &buffer.colorAttachments[i])
|
||||||
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[1])
|
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[i])
|
||||||
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(width), int32(height), 0, gl.RGB, gl.UNSIGNED_BYTE, nil)
|
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
|
||||||
gl.BindTexture(gl.TEXTURE_2D, 0)
|
|
||||||
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, buffer.colorAttachments[1], 0)
|
|
||||||
|
|
||||||
// material
|
|
||||||
gl.GenTextures(1, &buffer.colorAttachments[2])
|
|
||||||
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[2])
|
|
||||||
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(width), int32(height), 0, gl.RGB, gl.UNSIGNED_BYTE, nil)
|
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
|
||||||
gl.BindTexture(gl.TEXTURE_2D, 0)
|
|
||||||
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.TEXTURE_2D, buffer.colorAttachments[2], 0)
|
|
||||||
|
|
||||||
// position
|
|
||||||
gl.GenTextures(1, &buffer.colorAttachments[3])
|
|
||||||
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[3])
|
|
||||||
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(width), int32(height), 0, gl.RGB, gl.FLOAT, nil)
|
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(width), int32(height), 0, gl.RGB, gl.FLOAT, nil)
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||||
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||||
gl.BindTexture(gl.TEXTURE_2D, 0)
|
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||||
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT3, gl.TEXTURE_2D, buffer.colorAttachments[3], 0)
|
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i, gl.TEXTURE_2D, buffer.colorAttachments[i], 0)
|
||||||
|
i++
|
||||||
|
|
||||||
|
// material
|
||||||
|
gl.GenTextures(1, &buffer.colorAttachments[i])
|
||||||
|
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[i])
|
||||||
|
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(width), int32(height), 0, gl.RGB, gl.FLOAT, nil)
|
||||||
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||||
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||||
|
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||||
|
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i, gl.TEXTURE_2D, buffer.colorAttachments[i], 0)
|
||||||
|
i++
|
||||||
|
|
||||||
|
// position
|
||||||
|
gl.GenTextures(1, &buffer.colorAttachments[i])
|
||||||
|
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[i])
|
||||||
|
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(width), int32(height), 0, gl.RGB, gl.FLOAT, nil)
|
||||||
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||||||
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||||||
|
gl.BindTexture(gl.TEXTURE_2D, 0)
|
||||||
|
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i, gl.TEXTURE_2D, buffer.colorAttachments[i], 0)
|
||||||
|
i++
|
||||||
|
|
||||||
if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE {
|
if gl.CheckFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE {
|
||||||
return buffer, errors.New("failed to create framebuffer")
|
return buffer, errors.New("failed to create framebuffer")
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
package geometry
|
package geometry
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
"github.com/go-gl/gl/v4.6-core/gl"
|
"github.com/go-gl/gl/v4.6-core/gl"
|
||||||
|
"github.com/go-gl/mathgl/mgl32"
|
||||||
"github.com/udhos/gwob"
|
"github.com/udhos/gwob"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -9,6 +12,7 @@ import (
|
|||||||
// position 3 * float
|
// position 3 * float
|
||||||
// texture 2 * float
|
// texture 2 * float
|
||||||
// normal 3 * float
|
// normal 3 * float
|
||||||
|
// tangent 3 * float
|
||||||
|
|
||||||
type Geometry struct {
|
type Geometry struct {
|
||||||
vao uint32
|
vao uint32
|
||||||
@ -46,18 +50,28 @@ func new(coords []float32, indicies []int) (Geometry, error) {
|
|||||||
gl.BindBuffer(gl.ARRAY_BUFFER, geometry.vbo)
|
gl.BindBuffer(gl.ARRAY_BUFFER, geometry.vbo)
|
||||||
gl.BufferData(gl.ARRAY_BUFFER, len(coords)*4, gl.Ptr(coords), gl.STATIC_DRAW)
|
gl.BufferData(gl.ARRAY_BUFFER, len(coords)*4, gl.Ptr(coords), gl.STATIC_DRAW)
|
||||||
|
|
||||||
|
var i uint32 = 0
|
||||||
|
|
||||||
// attributes
|
// attributes
|
||||||
// position
|
// position
|
||||||
gl.VertexAttribPointerWithOffset(0, 3, gl.FLOAT, false, 8*4, 0)
|
gl.VertexAttribPointerWithOffset(i, 3, gl.FLOAT, false, 11*4, 0)
|
||||||
gl.EnableVertexAttribArray(0)
|
gl.EnableVertexAttribArray(i)
|
||||||
|
i++
|
||||||
|
|
||||||
// texture
|
// texture
|
||||||
gl.VertexAttribPointerWithOffset(1, 2, gl.FLOAT, false, 8*4, 3*4)
|
gl.VertexAttribPointerWithOffset(i, 2, gl.FLOAT, false, 11*4, 3*4)
|
||||||
gl.EnableVertexAttribArray(1)
|
gl.EnableVertexAttribArray(i)
|
||||||
|
i++
|
||||||
|
|
||||||
// normal
|
// normal
|
||||||
gl.VertexAttribPointerWithOffset(2, 3, gl.FLOAT, false, 8*4, 5*4)
|
gl.VertexAttribPointerWithOffset(2, 3, gl.FLOAT, false, 11*4, 5*4)
|
||||||
gl.EnableVertexAttribArray(2)
|
gl.EnableVertexAttribArray(i)
|
||||||
|
i++
|
||||||
|
|
||||||
|
// tangent
|
||||||
|
gl.VertexAttribPointerWithOffset(i, 3, gl.FLOAT, false, 11*4, 8*4)
|
||||||
|
gl.EnableVertexAttribArray(i)
|
||||||
|
i++
|
||||||
|
|
||||||
// ebo
|
// ebo
|
||||||
gl.GenBuffers(1, &geometry.ebo)
|
gl.GenBuffers(1, &geometry.ebo)
|
||||||
@ -68,23 +82,85 @@ func new(coords []float32, indicies []int) (Geometry, error) {
|
|||||||
return geometry, nil
|
return geometry, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadOBJ(path string) (geometries Geometry, err error) {
|
func LoadOBJ(path string) (geometry Geometry, err error) {
|
||||||
o, err := gwob.NewObjFromFile(path, &gwob.ObjParserOptions{})
|
o, err := gwob.NewObjFromFile(path, &gwob.ObjParserOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return geometries, err
|
return geometry, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return new(o.Coord, o.Indices)
|
if !o.NormCoordFound {
|
||||||
|
return geometry, errors.New("missing normals in OBJ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !o.TextCoordFound {
|
||||||
|
return geometry, errors.New("missing texture UVs in OBJ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// add tangent
|
||||||
|
coords := make([]float32, 0, len(o.Coord)*11)
|
||||||
|
tangents := make([][3]float32, len(o.Coord)/8)
|
||||||
|
|
||||||
|
// iterate faces
|
||||||
|
for i := 0; i < len(o.Indices); i += 3 {
|
||||||
|
i0 := o.Indices[i+0]
|
||||||
|
i1 := o.Indices[i+1]
|
||||||
|
i2 := o.Indices[i+2]
|
||||||
|
|
||||||
|
// positions
|
||||||
|
v0 := o.Coord[i0*8 : i0*8+3]
|
||||||
|
v1 := o.Coord[i1*8 : i1*8+3]
|
||||||
|
v2 := o.Coord[i2*8 : i2*8+3]
|
||||||
|
|
||||||
|
// UVs
|
||||||
|
uv0 := o.Coord[i0*8+3 : i0*8+5]
|
||||||
|
uv1 := o.Coord[i1*8+3 : i1*8+5]
|
||||||
|
uv2 := o.Coord[i2*8+3 : i2*8+5]
|
||||||
|
|
||||||
|
// edges
|
||||||
|
edge1 := [3]float32{v1[0] - v0[0], v1[1] - v0[1], v1[2] - v0[2]}
|
||||||
|
edge2 := [3]float32{v2[0] - v0[0], v2[1] - v0[1], v2[2] - v0[2]}
|
||||||
|
|
||||||
|
// UV deltas
|
||||||
|
delta1 := [2]float32{uv1[0] - uv0[0], uv1[1] - uv0[1]}
|
||||||
|
delta2 := [2]float32{uv2[0] - uv0[0], uv2[1] - uv0[1]}
|
||||||
|
|
||||||
|
// calculate tangents
|
||||||
|
f := 1.0 / (delta1[0]*delta2[1] - delta2[0]*delta1[1])
|
||||||
|
tangent := [3]float32{
|
||||||
|
f * (delta2[1]*edge1[0] - delta1[1]*edge2[0]),
|
||||||
|
f * (delta2[1]*edge1[1] - delta1[1]*edge2[1]),
|
||||||
|
f * (delta2[1]*edge1[2] - delta1[1]*edge2[2]),
|
||||||
|
}
|
||||||
|
|
||||||
|
tangents[i0] = mgl32.Vec3(tangents[i0]).Add(tangent)
|
||||||
|
tangents[i1] = mgl32.Vec3(tangents[i1]).Add(tangent)
|
||||||
|
tangents[i2] = mgl32.Vec3(tangents[i2]).Add(tangent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// build coords
|
||||||
|
for i := 0; i < len(o.Coord)/8; i++ {
|
||||||
|
pos := o.Coord[i*8 : i*8+3]
|
||||||
|
uv := o.Coord[i*8+3 : i*8+5]
|
||||||
|
norm := o.Coord[i*8+5 : i*8+8]
|
||||||
|
tan := mgl32.Vec3(tangents[i]).Normalize()
|
||||||
|
|
||||||
|
coords = append(coords, pos...)
|
||||||
|
coords = append(coords, uv...)
|
||||||
|
coords = append(coords, norm...)
|
||||||
|
coords = append(coords, tan[0:3]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return new(coords, o.Indices)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Screen() (Geometry, error) {
|
func Screen() (Geometry, error) {
|
||||||
return new(
|
return new(
|
||||||
[]float32{
|
[]float32{
|
||||||
// xyz uv ijk
|
// xyz, uv, nrm, tan
|
||||||
-1, -1, 0, 0, 0, 0, 0, 0,
|
-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
1, -1, 0, 1, 0, 0, 0, 0,
|
1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||||
-1, 1, 0, 0, 1, 0, 0, 0,
|
-1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
1, 1, 0, 1, 1, 0, 0, 0,
|
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||||
},
|
},
|
||||||
[]int{
|
[]int{
|
||||||
0, 1, 2,
|
0, 1, 2,
|
||||||
|
Loading…
Reference in New Issue
Block a user