using DesignatedShader
using GLFW
using ModernGL
using GeometryTypes
using FileIO, MeshIO
using LinearAlgebra
using CImGui
using CSyntax
using CSyntax.CStatic
using CImGui.GLFWBackend
using CImGui.OpenGLBackend
const cat_obj = load("assets/cat.obj")
const WH = 640
const glsl_version = 150
GLFW.WindowHint(GLFW.CONTEXT_VERSION_MAJOR, 3)
GLFW.WindowHint(GLFW.CONTEXT_VERSION_MINOR, 3)
GLFW.WindowHint(GLFW.OPENGL_PROFILE, GLFW.OPENGL_CORE_PROFILE)
GLFW.WindowHint(GLFW.OPENGL_FORWARD_COMPAT, GL_TRUE)
error_callback(err::GLFW.GLFWError) = @error "GLFW ERROR: code $(err.code) msg: $(err.description)"
GLFW.SetErrorCallback(error_callback)
win = GLFW.CreateWindow(WH, WH, "DesignatedShader")
GLFW.MakeContextCurrent(win)
GLFW.ShowWindow(win)
GLFW.SwapInterval(1) # enable vsync
# setup Dear ImGui context
ctx = CImGui.CreateContext()
# setup Dear ImGui style
CImGui.StyleColorsDark()
# setup Platform/Renderer bindings
ImGui_ImplGlfw_InitForOpenGL(win, true)
ImGui_ImplOpenGL3_Init(glsl_version)
glViewport(0, 0, WH, WH)
DesignatedShader.createcontextinfo()
# Create scene for off-screen rendering
off_scene = Scene()
# Simple single-component lighting
const simple_vsh = """
$(get_glsl_version_string())
in vec3 position;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
void main() {
gl_Position = projection * view * model * vec4(position, 1.0);
//gl_Position = vec4(position, 1.0);
}
"""
const simple_fsh = """
$(get_glsl_version_string())
layout (location = 0) out vec3 outColor;
void main() {
outColor = vec3(1.0, 0.0, 1.0);
}
"""
# Blinn-phong shading
const phong_vsh = """
$(get_glsl_version_string())
in vec3 position;
in vec3 inputNormal;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
out vec3 normalInterp;
out vec3 vertPos;
float rand(vec2 co){
return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);
}
void main() {
gl_Position = projection * view * model * vec4(position, 1.0);
vec4 vertPos4 = view * model * vec4(position, 1.0);
vertPos = vec3(vertPos4) / vertPos4.w;
mat3 normalMat = transpose(inverse(vec4(inputNormal, 1.0)));
normalInterp = vec3(normalMat * vec4(inputNormal, 0.0));
}
"""
const phong_fsh = """
$(get_glsl_version_string())
precision mediump float;
uniform int mode = 1;
in vec3 normalInterp;
in vec3 vertPos;
layout (location = 0) out vec3 outColor;
uniform vec3 lightPos;
const vec3 lightColor = vec3(1.0, 0.0, 1.0);
const float lightPower = 40.0;
const vec3 ambientColor = vec3(0.1, 0.0, 0.0);
const vec3 diffuseColor = vec3(0.5, 0.0, 0.0);
const vec3 specColor = vec3(1.0, 1.0, 1.0);
const float shininess = 16.0;
const float screenGamma = 2.2; // Assume the monitor is calibrated to the sRGB color space
void main() {
vec3 normal = normalize(normalInterp);
vec3 lightDir = lightPos - vertPos;
float distance = length(lightDir);
distance = distance * distance;
lightDir = normalize(lightDir);
float lambertian = max(dot(lightDir,normal), 0.0);
float specular = 0.0;
if (lambertian > 0.0) {
vec3 viewDir = normalize(-vertPos);
// this is blinn phong
vec3 halfDir = normalize(lightDir + viewDir);
float specAngle = max(dot(halfDir, normal), 0.0);
specular = pow(specAngle, shininess);
// this is phong (for comparison)
if(mode == 2) {
vec3 reflectDir = reflect(-lightDir, normal);
specAngle = max(dot(reflectDir, viewDir), 0.0);
// note that the exponent is different here
specular = pow(specAngle, shininess/4.0);
}
}
vec3 colorLinear = ambientColor +
diffuseColor * lambertian * lightColor * lightPower / distance +
specColor * specular * lightColor * lightPower / distance;
// apply gamma correction (assume ambientColor, diffuseColor and specColor
// have been linearized, i.e. have no gamma correction in them)
vec3 colorGammaCorrected = pow(colorLinear, vec3(1.0 / screenGamma));
// use the gamma corrected color in the fragment
outColor = colorGammaCorrected;
}
"""
set_shader!(off_scene; vert=simple_vsh,frag=simple_fsh)
dsf = DynamicShaderSpec(kind=:frag)
add_input!(dsf, "fragUV", DesignatedShader.GLSLType_vec2)
#add_uniform!(dsf, "tex", DesignatedShader.GLSLType_sampler2D)
add_output!(dsf, "outColor", DesignatedShader.GLSLType_vec4)
# TODO: assign!(dsf, "outColor", vec4(swizzle(sample_texture("tex", "fragUV"), "rgb"), 1.0))
show(dsf)
dsv = DynamicShaderSpec(kind=:vert)
add_input!(dsv, "input1", DesignatedShader.GLSLType_vec2)
add_input!(dsv, "input2", DesignatedShader.GLSLType_mat4)
add_output!(dsv, "output", DesignatedShader.GLSLType_vec3)
show(dsv)
# Setup off-screen rendering
set_output!(off_scene, create_framebuffer(), 640, 640)
add_depthbuffer!(off_scene, create_renderbuffer())
offTex = create_texture()
load_data!(offTex, C_NULL, 640, 640)
set_output_texture!(off_scene, offTex)
#texSize = 64
#texData = rand(Vec3f0, texSize, texSize)
#tex = create_texture()
#load_data!(tex, texData, texSize, texSize)
#add_texture!(off_scene, "tex", tex)
# Create scene for on-screen rendering
on_scene = Scene()
# Enable depth test
glEnable(GL_DEPTH_TEST)
# Accept fragment if it closer to the camera than the former one
glDepthFunc(GL_LESS)
glClearColor(0.2, 0.2, 0.2, 1.0)
function color_func(data)
color_data = Vector{Point3f0}(undef, length(data))
for idx in 1:length(data)
color_data[idx] = Point3f0(rand(Float32), rand(Float32), rand(Float32))
end
return color_data
end
function uv_func(data)
uv_data = Vector{Point2f0}(undef, length(data))
for idx in 1:length(data)
uv_data[idx] = Point2f0(idx/length(data), idx/length(data))
end
return uv_data
end
while !GLFW.WindowShouldClose(win)
# Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame()
ImGui_ImplGlfw_NewFrame()
CImGui.NewFrame()
# Generate some primitives
theta = time_ns() / 1_000_000_000
M = zeros(Float32, 4, 4) + I
M[1,1] = cos(theta)
M[3,1] = -sin(theta)
M[1,3] = sin(theta)
M[3,3] = cos(theta)
M[4,4] = 1f0
V = zeros(Float32, 4, 4) + I
P = zeros(Float32, 4, 4) + I
#push_primitive!(off_scene, HyperRectangle(Vec3f0(0.5,0,0.5), Vec3f0(0.5f0)), (UV=uv_func,))
#push_primitive!(off_scene, HyperRectangle(Vec3f0(0.5,0,0), Vec3f0(0.5f0)), (UV=uv_func,))
#push_primitive!(off_scene, HyperRectangle(Vec3f0(0.5,0,-0.5), Vec3f0(0.5f0)), (UV=uv_func,))
push_primitive!(off_scene, HyperSphere(Point3f0(0), 0.5f0),
#(inputNormal=(DesignatedShader.get_normals,GL_FLOAT,3),),
NamedTuple(),
(model=M,view=V,projection=P,))
#lightPos=Vec3f0(cos(theta), 0.0, -sin(theta)),))
#push_primitive!(off_scene, cat_obj, (inputNormal=((_)->cat_obj.normals,GL_FLOAT,3),))
# Render to texture
DesignatedShader.render(off_scene)
# Render to display
use_scene!(on_scene; size=(off_scene.output[].size))
# ImGui stuff
CImGui.Begin("A Window")
CImGui.Text("Some text")
# Render local scene
# FIXME: Get correct texture size
img_width = 1024
img_height = 768
CImGui.Image(Ptr{Cvoid}(Int(offTex)), (img_width, img_height))
CImGui.End() # Begin("A Window")
# rendering
CImGui.Render()
GLFW.MakeContextCurrent(win)
display_w, display_h = GLFW.GetFramebufferSize(win)
glViewport(0, 0, display_w, display_h)
ImGui_ImplOpenGL3_RenderDrawData(CImGui.GetDrawData())
# Swap and poll
GLFW.MakeContextCurrent(win)
GLFW.SwapBuffers(win)
GLFW.PollEvents()
sleep(1/30)
end
ImGui_ImplOpenGL3_Shutdown()
ImGui_ImplGlfw_Shutdown()
CImGui.DestroyContext(ctx)
GLFW.DestroyWindow(win)