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 norm;
|
||||
in vec2 tex;
|
||||
in mat3 TBN;
|
||||
|
||||
layout (location = 0) out vec3 albedo;
|
||||
layout (location = 1) out vec3 normal;
|
||||
@ -16,10 +17,10 @@ layout (location = 2) out vec3 material;
|
||||
layout (location = 3) out vec3 position;
|
||||
|
||||
void main() {
|
||||
position = pos;
|
||||
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.y = texture(s_roughness, tex).y;
|
||||
material.z = texture(s_metalic, tex).z;
|
||||
position = pos;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
layout (location = 0) in vec3 _pos;
|
||||
layout (location = 1) in vec2 _tex;
|
||||
layout (location = 2) in vec3 _norm;
|
||||
layout (location = 3) in vec3 _tan;
|
||||
|
||||
uniform mat4 projection;
|
||||
uniform mat4 view;
|
||||
@ -11,8 +12,14 @@ uniform mat4 model;
|
||||
out vec3 pos;
|
||||
out vec3 norm;
|
||||
out vec2 tex;
|
||||
out mat3 TBN;
|
||||
|
||||
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);
|
||||
pos = vec3(model * vec4(_pos, 1.0));
|
||||
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 material; // specular, roughness, metalic
|
||||
vec3 position;
|
||||
vec2 texture_coords;
|
||||
|
||||
float specular;
|
||||
float roughness;
|
||||
float metalic;
|
||||
|
||||
vec3 calc_light(light_t light) {
|
||||
// diffuse
|
||||
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 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 - roughness) * specular;
|
||||
float spec = pow(max(dot(view_dir, reflect_dir), 0), 32);
|
||||
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() {
|
||||
albedo = texture(s_albedo, tex).rgb;
|
||||
albedo = pow(texture(s_albedo, tex).rgb, vec3(2.2));
|
||||
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;
|
||||
{
|
||||
specular = material.x;
|
||||
roughness = material.y;
|
||||
roughness = 1 - material.y;
|
||||
metalic = material.z;
|
||||
}
|
||||
position = texture(s_position, tex).xyz;
|
||||
|
||||
vec3 light_result;
|
||||
vec3 light_result = vec3(0.1);
|
||||
for (int i = 0; i < light_count; i++) {
|
||||
light_result += calc_light(lights[i]);
|
||||
}
|
||||
|
26
main.go
26
main.go
@ -73,11 +73,13 @@ func main() {
|
||||
}
|
||||
defer deferredShader.Delete()
|
||||
|
||||
vertexSource, err = os.ReadFile("assets/shader/screen/screen.vs")
|
||||
vertexSource, err = os.ReadFile("assets/shader/pbr/pbr.vs")
|
||||
if err != nil {
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
@ -144,10 +146,23 @@ func main() {
|
||||
}
|
||||
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 := []light.Light{
|
||||
{Color: [3]float32{0, 1, 0}, Position: mgl32.Vec3{3, 3, 3}, Intensity: 15, Type: light.POINT},
|
||||
{Color: [3]float32{1, 0, 1}, 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, 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
|
||||
@ -161,14 +176,13 @@ func main() {
|
||||
// transformations
|
||||
projection := mgl32.Perspective(mgl32.DegToRad(FOV), float32(WIDTH)/HEIGHT, 0.1, 1000)
|
||||
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() {
|
||||
glfw.PollEvents()
|
||||
controls.Update()
|
||||
|
||||
// first pass
|
||||
// bind textures
|
||||
gl.Enable(gl.DEPTH_TEST)
|
||||
|
||||
gbuff.Bind()
|
||||
|
@ -12,7 +12,7 @@ type GBuffer struct {
|
||||
colorAttachments [4]uint32 // albedo, normal, material, position
|
||||
}
|
||||
|
||||
var attachments = []uint32{
|
||||
var attachments = [...]uint32{
|
||||
gl.COLOR_ATTACHMENT0,
|
||||
gl.COLOR_ATTACHMENT1,
|
||||
gl.COLOR_ATTACHMENT2,
|
||||
@ -25,18 +25,23 @@ func (b *GBuffer) Bind() {
|
||||
}
|
||||
|
||||
func (b *GBuffer) BindTextures() {
|
||||
// albedo
|
||||
gl.ActiveTexture(gl.TEXTURE0)
|
||||
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[0])
|
||||
|
||||
// depth
|
||||
gl.ActiveTexture(gl.TEXTURE1)
|
||||
gl.BindTexture(gl.TEXTURE_2D, b.depth)
|
||||
|
||||
// normal
|
||||
gl.ActiveTexture(gl.TEXTURE2)
|
||||
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[1])
|
||||
|
||||
// material
|
||||
gl.ActiveTexture(gl.TEXTURE3)
|
||||
gl.BindTexture(gl.TEXTURE_2D, b.colorAttachments[2])
|
||||
|
||||
// position
|
||||
gl.ActiveTexture(gl.TEXTURE4)
|
||||
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.BindFramebuffer(gl.FRAMEBUFFER, buffer.framebuffer)
|
||||
|
||||
var i uint32 = 0
|
||||
|
||||
// albedo
|
||||
gl.GenTextures(1, &buffer.colorAttachments[0])
|
||||
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[0])
|
||||
gl.TexImage2D(gl.TEXTURE_2D, 0, gl.RGB, int32(width), int32(height), 0, gl.RGB, gl.UNSIGNED_BYTE, nil)
|
||||
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, gl.TEXTURE_2D, buffer.colorAttachments[0], 0)
|
||||
gl.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i, gl.TEXTURE_2D, buffer.colorAttachments[i], 0)
|
||||
i++
|
||||
|
||||
// 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)
|
||||
|
||||
// normal
|
||||
gl.GenTextures(1, &buffer.colorAttachments[1])
|
||||
gl.BindTexture(gl.TEXTURE_2D, buffer.colorAttachments[1])
|
||||
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.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_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 {
|
||||
return buffer, errors.New("failed to create framebuffer")
|
||||
|
@ -1,7 +1,10 @@
|
||||
package geometry
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/go-gl/gl/v4.6-core/gl"
|
||||
"github.com/go-gl/mathgl/mgl32"
|
||||
"github.com/udhos/gwob"
|
||||
)
|
||||
|
||||
@ -9,6 +12,7 @@ import (
|
||||
// position 3 * float
|
||||
// texture 2 * float
|
||||
// normal 3 * float
|
||||
// tangent 3 * float
|
||||
|
||||
type Geometry struct {
|
||||
vao uint32
|
||||
@ -46,18 +50,28 @@ func new(coords []float32, indicies []int) (Geometry, error) {
|
||||
gl.BindBuffer(gl.ARRAY_BUFFER, geometry.vbo)
|
||||
gl.BufferData(gl.ARRAY_BUFFER, len(coords)*4, gl.Ptr(coords), gl.STATIC_DRAW)
|
||||
|
||||
var i uint32 = 0
|
||||
|
||||
// attributes
|
||||
// position
|
||||
gl.VertexAttribPointerWithOffset(0, 3, gl.FLOAT, false, 8*4, 0)
|
||||
gl.EnableVertexAttribArray(0)
|
||||
gl.VertexAttribPointerWithOffset(i, 3, gl.FLOAT, false, 11*4, 0)
|
||||
gl.EnableVertexAttribArray(i)
|
||||
i++
|
||||
|
||||
// texture
|
||||
gl.VertexAttribPointerWithOffset(1, 2, gl.FLOAT, false, 8*4, 3*4)
|
||||
gl.EnableVertexAttribArray(1)
|
||||
gl.VertexAttribPointerWithOffset(i, 2, gl.FLOAT, false, 11*4, 3*4)
|
||||
gl.EnableVertexAttribArray(i)
|
||||
i++
|
||||
|
||||
// normal
|
||||
gl.VertexAttribPointerWithOffset(2, 3, gl.FLOAT, false, 8*4, 5*4)
|
||||
gl.EnableVertexAttribArray(2)
|
||||
gl.VertexAttribPointerWithOffset(2, 3, gl.FLOAT, false, 11*4, 5*4)
|
||||
gl.EnableVertexAttribArray(i)
|
||||
i++
|
||||
|
||||
// tangent
|
||||
gl.VertexAttribPointerWithOffset(i, 3, gl.FLOAT, false, 11*4, 8*4)
|
||||
gl.EnableVertexAttribArray(i)
|
||||
i++
|
||||
|
||||
// ebo
|
||||
gl.GenBuffers(1, &geometry.ebo)
|
||||
@ -68,23 +82,85 @@ func new(coords []float32, indicies []int) (Geometry, error) {
|
||||
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{})
|
||||
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) {
|
||||
return new(
|
||||
[]float32{
|
||||
// xyz uv ijk
|
||||
-1, -1, 0, 0, 0, 0, 0, 0,
|
||||
1, -1, 0, 1, 0, 0, 0, 0,
|
||||
-1, 1, 0, 0, 1, 0, 0, 0,
|
||||
1, 1, 0, 1, 1, 0, 0, 0,
|
||||
// xyz, uv, nrm, tan
|
||||
-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
-1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,
|
||||
1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
|
||||
},
|
||||
[]int{
|
||||
0, 1, 2,
|
||||
|
Loading…
Reference in New Issue
Block a user