-
-
Notifications
You must be signed in to change notification settings - Fork 324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lighting attributes #27
Comments
In link with lighting questions. The following example show an illumination different for spheres and cylinders whereas the source light seems to be the same. From one side, the spheres are brighting whereas the cylinder are dark and reversely on the other side of the grid. I suspect an orientation choice but this should only affect interior/exterior lighting differences of cylinders, no ? using GeometryTypes, Makie
scene = Scene(resolution = (500, 500))
δx = 0.1; h1 = []; h2= []
for x in 0:δx:1
for y in 0:δx:1
h1 = mesh(Sphere(Point3f0(x, y, 0), Float32(δx * 0.35)))
h2 = mesh(GLNormalMesh(Cylinder(Point3f0(x, y, 0),
Point3f0(x + δx, y, 0),
Float32(δx * 0.3)), 10))
end
end
println(h1[:light])
println(h2[:light]) |
The lighting of the cylinders, pyramids, cubes and cats seems to be compatible and coherent with a light coming from using GeometryTypes, Makie, GLVisualize
scene = Scene(resolution = (500, 500))
δx = 0.1; nbc = 5; it = 0; h = []
for x in 0:δx:1
for y in 0:δx:1
h = if mod(it, nbc) == 0
objG = Sphere(Point3f0(x, y, 0), Float32(δx * 0.35))
mesh(GLNormalMesh(objG, 30))
elseif mod(it, nbc) == 1
objG = Cylinder(Point3f0(x - δx / 2, y, 0), Point3f0(x + δx / 2, y, 0),
Float32(δx * 0.3))
mesh(GLNormalMesh(objG, 30))
elseif mod(it, nbc) == 2
objG = GLVisualize.loadasset("cat.obj")
meshscatter([Vec3f0(x, y, 0),], marker = GLNormalMesh(objG), markersize = 1.5 * δx)
elseif mod(it, nbc) == 3
objG = GeometryTypes.HyperRectangle(Vec3f0(- 1 / 2), Vec3f0(1 / 2))
meshscatter([Vec3f0(x, y, 0),], marker = GLNormalMesh(objG), markersize = 1. * δx)
elseif mod(it, nbc) == 4
objG = GeometryTypes.Pyramid(Point3f0(0), 1f0, 1f0)
meshscatter([Vec3f0(x, y, 0),], marker = GLNormalMesh(objG), markersize = 1. * δx)
end
it += 1
end
end
println(h[:light])
Makie.axis(linspace(0, 1, 4), linspace(0, 1, 4), linspace(0, 1, 4))
Makie.center!(scene) |
Should be fixed by the PR |
@SimonDanisch I am interested in looking at the possibilities to extend lighting options in Makie. Where should I start? I guess reflectance properties have first to be accessible in GLVisualize? |
You can start by changing this shader to use uniforms instead of hard coded values: https://github.com/JuliaGL/GLVisualize.jl/blob/master/assets/shader/standard.frag#L47 You can first do something like changing the hard coded uniform vec3 diffuse_amount = vec3(0.1); And then this should already work in a non breaking fashion: _view(visualize(mesh, diffuse_amount = Vec3f0(0.5))) Then you can start putting the defaults in: And that's pretty much it :) The bigger change will be to have something that is global to a scene. But I think this will come pretty naturally in Makie! |
Thank you for the precise road map! Nice, I will try this. return vec3(
vec3(0.1) * vec3(0.3) +
vec3(0.9) * color * diff_coeff +
vec3(0.3) * spec_coeff
); have to be hard coded or they correspond to classical parameters? If it is the case what could be their name? I tried to identify them but their is plenty of different formula related to blinnphong.. Finally, I noticed that the |
I just have a more careful look to your last pointer and understood that _default_light = Vec3f0[Vec3f0(1.0,1.0,1.0), Vec3f0(0.1,0.1,0.1), Vec3f0(0.9,0.9,0.9), Vec3f0(20,20,20)] I see the |
in this order:
Yes :) Have a look at https://en.wikipedia.org/wiki/Blinn%E2%80%93Phong_shading_model to get an idea |
OK, I will have a look when I find some time and let you know. Thanks for the details. |
Some conclusions and (too much) questions. Based on wikipedia Blinn-Phong as suggested.
Fact that should be checked can I effectively conclude that
and implement the new descriptions.
using GLVisualize, GeometryTypes, GLAbstraction, Colors, FileIO
window = GLVisualize.glscreen()
lightd = Vec3f0[Vec3f0(1.0,1.0,1.0), Vec3f0(0.1,0.1,0.1), Vec3f0(0.9,0.9,0.9), Vec3f0(0,0,200)]
for x = 0:2
for y = 0:2
dc = linspace(0, 2, 3)[x + 1]
sc = linspace(0, 2, 3)[y + 1]
sphere_mesh = GLNormalMesh(Sphere{Float32}(Point3f0(x, y, 0), 0.5f0), 50)
GLVisualize._view(GLVisualize.visualize(sphere_mesh, color = RGBA{Float32}(1, 0, 0, 1.),
ambientcolor = Vec3f0(0.01),
diffusioncolor = Vec3f0(dc),
specularcolor = Vec3f0(sc),
light = lightd, shininess = Float32(3.)),
window)
end
end
GLVisualize.renderloop(window) |
Proposal to be checked Perhaps adding 3 last (?) intensity parameters ambientintensity * ambientcolor
+ diffuseintensity * diffusecolor * diff_coeff * color
+ specularintensity * specularcolor * spec_coeff * color and the 4 new parameters ( At least this seems to be compatible with parameters illustrated in matlab help. It would remain to define default parameters :-( and to connect the light fileds with these parameter. |
With the above formulation, I tried to reproduce the two illustrations of matlab's help with the default parameters
The first tests seem to correspond whereas the results of the second one seem to me different but more intuitive.. window = GLVisualize.glscreen()
lightd = Vec3f0[Vec3f0(1.0,1.0,1.0), Vec3f0(0.1,0.1,0.1), Vec3f0(0.9,0.9,0.9), Vec3f0(0,0,200)]
for x = 0:2
for y = 0:2
dc = linspace(0, 1, 3)[x + 1]
sc = linspace(0, 1, 3)[2 - y + 1]
sphere_mesh = GLNormalMesh(Sphere{Float32}(Point3f0(x, y, 0), 0.45f0), 50)
GLVisualize._view(GLVisualize.visualize(sphere_mesh, color = RGBA{Float32}(1, 0, 0, 1.),
ambientcolor = Vec3f0(0.03),
diffusecolor = Vec3f0(0.9),
specularcolor = Vec3f0(0.3),
light = lightd, shininess = Float32(8.),
ambientintensity = Float32(1),
diffuseintensity = Float32(dc),
specularintensity = Float32(sc)),
window)#, camera = :orthographic_pixel)
end
end
for x = 0:2
for y = 0:2
ac = if x == 0
[0, 1, 0]
elseif x == 1
[0.5, 0, 1]
elseif x == 2
ones(3)
end
as = linspace(0, 1 / 2, 3)[y + 1]
sphere_mesh = GLNormalMesh(Sphere{Float32}(Point3f0(x , 2 - y - 4, 0), 0.45f0), 50)
GLVisualize._view(GLVisualize.visualize(sphere_mesh, color = RGBA{Float32}(1, 0, 0, 1.),
ambientcolor = Vec3f0(ac...),
diffusecolor = Vec3f0(0.9),
specularcolor = Vec3f0(0.3),
light = lightd, shininess = Float32(8.),
ambientintensity = Float32(as),
diffuseintensity = Float32(1.),
specularintensity = Float32(1.)),
window)#, camera = :orthographic_pixel)
end
end
GLVisualize.renderloop(window) |
Hm, I would have thought that the ambient light should change the color :D https://cglearn.codelight.eu/pub/computer-graphics/shading-and-lighting |
It affects definitely the color (second test on the right) but it only
changes dramatically the color if its intensity is sufficient..
Le 07/12/2017 à 11:33, Simon a écrit :
…
Hm, I would have thought that the ambient light should change the
color :D
https://cglearn.codelight.eu/pub/computer-graphics/shading-and-lighting
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<https://github.com/SimonDanisch/Makie.jl/issues/27#issuecomment-349928150>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AOTEe-UGgU_JZU3XHoaU1kQJz3pW82PQks5s978LgaJpZM4Qx8ce>.
--
Edouard Oudet : http://www-ljk.imag.fr/membres/Edouard.Oudet/
IMAG - Bureau 164
700 avenue Centrale
38400 Saint Martin d'Hères
+33 (0)4 57 42 17 71 (office LJK)
+33 (0)4 79 68 82 06 (home)
|
I mean compared to matlab, your results seem more likely ;) |
ah ok ;-), yes in fact ! |
They probably developed a plotting friendly shading model, that doesn't become super white and doesn't change the color too much ;) |
Still some remarks on the lighting
|
@SimonDanisch I guess points (1) above requires a global point of view of the design of |
What is exactly the problem? just pass the data as a keyword argument to GLVisualize and it should pick it up automatically. For Makie, that's not always true since I do some filtering, but we could include it ;)
|
(1) & (3) Ah, I see, when you write uniform you mean a single light. "The problem" was for me precisely related to several lights: I do not know how to attach the (global/uniform) parameters to a specific light. Actually, I understood that this possibility does not exist for the moment but it seems to me that it is perhaps more efficient to define the strategy to have several lights before to give the possibility to adjust parameters, no? (2) You mean only keep the definition of |
struct Light{
vec3 color;
vec3 position;
...
};
uniform Light[5] lights; // 5 lights But sadly the infrastructure in GLAbstraction isn't ready for that quite yet. GLSL does it best to make arrays of structs awkward. I've some prototypes for this, but was never 100% sure how to integrate it into the current design. Let me think about this, maybe there is an easy adhoc solution!
|
I just found this which looks very close to what we are looking for. Also the fields of a light are a little bit different but seem more generic! Additionally, it also implements the material properties which could be very convenient in some specific situations. I could try to follow very closely (~ copy / paste) this code or do you see source of troubles in Last naive question: Is the |
Well, that's very close to what I've suggested, and comes exactly with the problems I mentioned... Yes, I think the |
Ah ok sorry, this is the GLAbstraction infrastructure point you mentioned related to GLSL structures. For me this pointer was a progress since I was not sure how to define/tune all these parameters and this piece of code seems to me generic enough for most situations. I guess you already had a look to it in the past ;-) |
Yes I did ;) Yeah passing arrays of struct to OpenGL is no fun... |
Actually, we could also use the convenient structure at julia level and pass an array of array if it is simpler. The crucial point would be the non fixed size of the array (== nb of lights). I guess it would have the same complexity..? |
I tried to have a look and it compiles..but the current experimental version gives me only black object :-).
varying vec4 position; // position of the vertex (and fragment) in world space Do we have access to the position in our context? I also read that
|
yes, material.diffuse == color |
OK cool! Thanks. Let's forget spotlights for the moment ;-) |
OK, I managed to make it work in a very pedestrian way. Sorry for the naivety of the code!! Finally
uniform vec3 ambientcolor;
const int numberOfLights = 5;
struct lightSource
{
vec3 color;
vec3 position;
int onoff; // == 0 or 1
};
uniform vec3 position1;
uniform vec3 position2;
uniform vec3 position3;
uniform vec3 position4;
uniform vec3 position5;
uniform vec3 colorlight1;
uniform vec3 colorlight2;
uniform vec3 colorlight3;
uniform vec3 colorlight4;
uniform vec3 colorlight5;
uniform int onoff1; uniform int onoff2;
uniform int onoff3; uniform int onoff4; uniform int onoff5;
lightSource light0 = lightSource(
colorlight1, // color
position1, // position
onoff1
);
lightSource light1 = lightSource(
colorlight2, // color
position2, // position
onoff2
);
lightSource light2 = lightSource(
colorlight3, // color
position3, // position
onoff3
);
lightSource light3 = lightSource(
colorlight4, // color
position4, // position
onoff4
);
lightSource light4 = lightSource(
colorlight5, // color
position5, // position
onoff5
);
lightSource lights[numberOfLights];
uniform vec4 material; //vec4(1., 0.4, 0.5, 1.);
/*
(ambient, diffuse, specular, specularcolorcoeff) ∈ [0, 1]
default vec4(1., 0.4, 0.5, 1.);
*/
uniform float shininess;
///////////////////////////////////////////////////////////////////////////////
struct Nothing{ //Nothing type, to encode if some variable doesn't contain any data
bool _; //empty structs are not allowed
};
in vec3 o_normal;
in vec3 o_lightdir;
in vec3 o_vertex;
in vec4 o_color;
in vec2 o_uv;
flat in uvec2 o_id;
{{color_type}} color;
vec4 get_color(vec3 color, vec2 uv){
return vec4(color, 1.0 + (0.0 * uv)); // we must prohibit uv from getting into dead variable removal
}
vec4 get_color(vec4 color, vec2 uv){
return color + uv.x * 0.0; // we must prohibit uv from getting into dead variable removal
}
vec4 get_color(Nothing color, vec2 uv){
return o_color + uv.x * 0.0;
}
vec4 get_color(samplerBuffer color, vec2 uv){
return o_color + uv.x * 0.0;
}
vec4 get_color(sampler2D color, vec2 uv){
return texture(color, uv);
}
/*
1) L light direction still needed as input parameters?
2) Term pow(max(0.0, dot(reflect(-L, N), V)), shininess) different
from first implementation??
*/
vec3 blinnphong(vec3 N, vec3 V, vec3 L, vec3 color){
// define lights
lights[0] = light0;
lights[1] = light1;
lights[2] = light2;
lights[3] = light3;
lights[4] = light4;
// initialize total lighting with ambient lighting
vec3 totalLighting = material[0] * vec3(ambientcolor);
for (int index = 0; index < numberOfLights; index++) // for all light sources
{
if (lights[index].onoff == 1)
{
//??? L
L = normalize(vec3(lights[index].position));
vec3 diffuseReflection = material[1] * vec3(lights[index].color) *
max(0.0, dot(N, L)) * color;
vec3 specularReflection;
if (dot(N, L) < 0.0) // light source on the wrong side?
{
specularReflection = vec3(0.0, 0.0, 0.0); // no specular reflection
}
else // light source on the right side
{
vec3 specularcolor = (1 - material[3]) * vec3(lights[index].color) +
material[3] *vec3(1);
specularReflection = material[2] * vec3(specularcolor) *
pow(max(dot(L, N), 0.0), shininess);
}
totalLighting = totalLighting + diffuseReflection + specularReflection;
}
}
return totalLighting;
} and the piece of code in vizualize_interface.jl is simply @gen_defaults! data begin # make sure every object has these!
model = eye(Mat4f0)
light = _default_light
preferred_camera = :perspective
is_transparent_pass = Cint(false)
# default lights attributes of a scene
material = Vec4f0(1., 0.4, 0.5, 1.) # (ambient, diffuse, specular, specularcolorcoeff) ∈ [0, 1]
shininess = Float32(8.); ambientcolor = Vec3f0(0.01)
onoff1 = 1; position1 = Vec3f0(10.0, 100.0, 200.0); colorlight1 = Vec3f0(1.)
onoff2 = 0; position2 = Vec3f0(10.0, 100.0, -200.0); colorlight2 = Vec3f0(1.)
onoff3 = 0; position3 = Vec3f0(10.0, 100.0, 200.0); colorlight3 = Vec3f0(1.)
onoff4 = 0; position4 = Vec3f0(10.0, 100.0, 200.0); colorlight4 = Vec3f0(1.)
onoff5 = 0; position5 = Vec3f0(10.0, 100.0, 200.0); colorlight5 = Vec3f0(1.)
end Illustration of two lights in a single scene and other material properties side 1/ side 2 and the example code window = GLVisualize.glscreen(); δ = 0.45
lightd = Vec3f0[Vec3f0(1.0, 1.0, 1.0), Vec3f0(0.1, 0.1, 0.1),
Vec3f0(0.9, 0.9, 0.9), Vec3f0(10, 50, 200)]
markerm = :o
#markerm = :□
for x = 0:2
for y = 0:2
dc = linspace(0, 0.5, 3)[x + 1]
sc = linspace(0, 0.5, 3)[2 - y + 1]
lmesh = if markerm == :o
GLNormalMesh(Sphere{Float32}(Point3f0(x, y, 0), Float32(δ)), 50)
elseif markerm == :□
GLNormalMesh(GeometryTypes.HyperRectangle(Vec3f0(x - δ, y - δ , - δ),
Vec3f0(3 * δ / 2, 3 * δ / 2 , 3 * δ / 2)))
end
material = Vec4f0(1, dc, sc, 1.)
GLVisualize._view(GLVisualize.visualize(lmesh, color = RGBA{Float32}(1, 0, 0, 1.),
light = lightd, shininess = Float32(8.),
material = material,
position1 = Vec3f0(100), onoff2 = 1, colorlight1 = Vec3f0(0.8),
ambientcolor = Vec3f0(0.01)), window)
end
end
cd = 1.
for x = 0:2
for y = 0:2
ac = if x == 0
[0, 1, 0]
elseif x == 1
[0.5, 0, 1]
elseif x == 2
ones(3)
end
ac /= cd
as = linspace(0, 0.5, 3)[y + 1]
lmesh = if markerm == :o
GLNormalMesh(Sphere{Float32}(Point3f0(x , 2 - y - 4, 0), Float32(δ)), 50)
elseif markerm == :□
GLNormalMesh(GeometryTypes.HyperRectangle(Vec3f0(x - δ, 2 - y - δ - 4 , - δ),
Vec3f0(3 * δ / 2, 3 * δ / 2 , 3 * δ / 2)))
end
material = Vec4f0(as, 0.4, 0.8, 1.)
GLVisualize._view(GLVisualize.visualize(lmesh, color = RGBA{Float32}(1, 0, 0, 1.),
ambientcolor = Vec3f0(ac...),
light = lightd, shininess = Float32(8.),
material = material), window)
end
end
GLVisualize.renderloop(window) |
Since the modifications described below, scene = Makie.Scene(resolution = (500, 500))
Makie.mesh(GLNormalMesh(Sphere{Float32}(Point3f0(0), Float32(1)), 50))
center!(scene) produces a colored shining sphere whereas scene = Makie.Scene(resolution = (500, 500))
Makie.meshscatter([Vec3f0(0),], maker = GLNormalMesh(Sphere{Float32}(Point3f0(0), Float32(1)), 50))
center!(scene) produces a black sphere (no light, no colors).. Any idea of what could be at the origin of the problem? |
You haven't updated particles.vert? |
No, should I? |
I guess, it also uses standard.frag, and I'm guessing it's not receiving the correct inputs? Or did you actually not touch any vertex shader at all? |
only gives me differences between the |
ah maybe, meshscatter doesn't pass through the attributes or something... |
can you open a PR so that I can have a look at it? |
Here it is lights attributes. Thanks. |
Changing the two lines into viz = visualize(main, Style(:default), gl_data).children[] seems to fix the problem |
I try to identify what could be a more general but still efficient and generic way of handling lighting. Let us first focalize on GLVisualize and the shader:
If we take that direction we need to:
|
It would give something like this PR |
Can we access/modify the lighting/reflectance properties of an object/mesh in Makie?
The text was updated successfully, but these errors were encountered: