Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 3 additions & 13 deletions plugins_src/primitives/wpc_image.erl
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ load_img_plane(FileName, #e3d_image{type=Type}=Image0) ->
wpa:error_msg(?__(1,"The image cannot be loaded as a texture.~nFile: \"~s\"~n GLU Error: ~p - ~s~n"),
[FileName,GlErr, wings_gl:error_string(GlErr)]);
Image0i ->
Image1 = e3d_image:convert(Image0i, img_type(Type), 1, lower_left),
Image1 = e3d_image:convert(Image0i, wings_image:img_type(Type), 1, lower_left),
#e3d_image{width=W0,height=H0} = Image1,
Image = case pad_image(Image1) of
Image1 ->
Expand Down Expand Up @@ -307,7 +307,7 @@ ratio(W, H) when W < H -> {1.0,H/W};
ratio(W, H) -> {W/H,1.0}.

pad_image(#e3d_image{width=W0,image=Pixels0,bytes_pp=PP}=Image) ->
case nearest_power_two(W0) of
case wings_image:nearest_power_two(W0) of
W0 ->
pad_image_1(Image);
W ->
Expand All @@ -317,7 +317,7 @@ pad_image(#e3d_image{width=W0,image=Pixels0,bytes_pp=PP}=Image) ->
end.

pad_image_1(#e3d_image{width=W,height=H0,image=Pixels0,bytes_pp=PP}=Image) ->
case nearest_power_two(H0) of
case wings_image:nearest_power_two(H0) of
H0 ->
pad_image_2(Image);
H ->
Expand Down Expand Up @@ -345,13 +345,3 @@ zeroes(N) when N rem 2 =:= 0 ->
zeroes(N) ->
Z = zeroes(N div 2),
[0,Z|Z].

nearest_power_two(N) ->
nearest_power_two(N, 1).

nearest_power_two(N, B) when N =< B -> B;
nearest_power_two(N, B) -> nearest_power_two(N, B bsl 1).

img_type(b8g8r8) -> r8g8b8;
img_type(b8g8r8a8) -> r8g8b8a8;
img_type(Type) -> Type.
File renamed without changes.
60 changes: 60 additions & 0 deletions shaders/matcap_light.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// $Id$
//
// Fragment shader for MatCap light
//
// Author: 2026 Micheus
//

#version 120

#include "lib_base.glsl"
#include "lib_normal.glsl"
#include "lib_material.glsl"


varying vec3 vs_position;
varying vec3 vs_normal;
varying mat3 wv_matrix;

uniform float MatCapRot;
uniform int MatCapUseDiffuse;
uniform sampler2D MatCapMap;


vec2 matcapUV(vec3 vec)
{
float ofs = 2.0*sqrt(vec.x*vec.x + vec.y*vec.y + (vec.z+1.0)*(vec.z+1.0));
vec2 uv = vec.xy/ofs+0.5;
return uv;
}

vec3 matcapRotate(vec3 v, float a) {
float c = cos(a);
float s = sin(a);
vec3 n = vec3(0.0,0.0,1.0);
return v*c + cross(n, v)*s + n*dot(n, v)*(1.0-c);
}

vec4 calcBasecolor(vec4 v_basecolor) {
if(MatCapUseDiffuse > 0) {
vec4 basecolor = get_basecolor();
return v_basecolor*basecolor;
} else
return v_basecolor;
}

void main() {
vec3 n = get_normal();

vec3 vN = normalize(wv_matrix * n); // convert world-space normal into view-space
vec3 vP = normalize(-vs_position); // view-space view vector (camera at origin)
vec3 r = reflect(-vP, vN); // reflection vector in view space
r = normalize(r);

vec3 Rr = matcapRotate(r, MatCapRot);
Rr = normalize(Rr);

vec2 uv = matcapUV(Rr);
vec4 basecolor = calcBasecolor(texture2D(MatCapMap, uv));
gl_FragColor = vec4(basecolor.rgb, 1.0);
}
9 changes: 9 additions & 0 deletions shaders/standard.vs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ varying vec4 ws_tangent; // world space
varying vec3 ws_position; // world space
varying vec4 v_basecolor;

varying vec3 vs_normal; // view space
varying vec3 vs_position; // view space
varying mat3 wv_matrix;

uniform mat3x4 ws_matrix;

vec4 SRGBtoLINEAR(vec4 srgbIn)
Expand All @@ -23,6 +27,11 @@ vec4 SRGBtoLINEAR(vec4 srgbIn)

void main(void)
{
vec4 viewPos4 = gl_ModelViewMatrix * gl_Vertex;
vs_position = viewPos4.xyz;
vs_normal = normalize(gl_NormalMatrix * gl_Normal);
wv_matrix = mat3(gl_ModelViewMatrix);

ws_position = mat3x3(ws_matrix)*gl_Vertex.xyz;
// ws_position = gl_Vertex.xyz;
v_basecolor = diffuse * SRGBtoLINEAR(gl_Color);
Expand Down
1 change: 1 addition & 0 deletions src/wings.hrl
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
-define(ENV_DIFF_MAP_UNIT, 3).
-define(ENV_SPEC_MAP_UNIT, 4).
-define(ENV_BRDF_MAP_UNIT, 5).
-define(MATCAP_MAP_UNIT, 7).
-define(AREA_LTC_MAT_UNIT, 8). %%
%% Extra materials
-define(EMISSION_MAP_UNIT, 6).
Expand Down
2 changes: 1 addition & 1 deletion src/wings_image.erl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
window/1, debug_display/2]).
-export([image_formats/0,image_read/1,image_write/1,
e3d_to_wxImage/1, wxImage_to_e3d/1, resize_image/3]).
-export([maybe_exceds_opengl_caps/1]).
-export([maybe_exceds_opengl_caps/1, img_type/1, nearest_power_two/1]).

-behavior(gen_server).
-export([start_link/0, init/1, handle_call/3, handle_cast/2]).
Expand Down
61 changes: 55 additions & 6 deletions src/wings_light.erl
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
%% Implementation of lights.
%%
%% Copyright (c) 2002-2011 Bjorn Gustavsson
%%
%% 2026 Micheus (support to matcap)
%% See the file "license.terms" for information on usage and redistribution
%% of this file, and for a DISCLAIMER OF ALL WARRANTIES.
%%
%% $Id$
%%

-module(wings_light).
-export([init/0, init/1, init_opengl/0, load_env_image/1,
-export([init/0, init/1, init_opengl/0, load_env_image/1, load_matcap_texture/1,
light_types/0,menu/3,command/2,is_any_light_selected/1,
any_enabled_lights/0,info/1,setup_light/2,
create/2,update_dynamic/2,update_matrix/2,update/1,
Expand Down Expand Up @@ -55,11 +55,19 @@ def_envmap() ->
DefPath = filename:join(wings_util:lib_dir(wings), "textures"),
filename:join(DefPath, DefEnvMap).

def_matcap() ->
DefMatCap = "LitSphere1.png",
DefPath = filename:join([wings_util:lib_dir(wings), "textures", "matcap"]),
filename:join(DefPath, DefMatCap).

init() ->
wings_pref:set_default(show_bg, false),
wings_pref:set_default(show_bg_blur, 0.5),
wings_pref:set_default(show_bg_rotate, 0.0),
wings_pref:set_default(bg_image, def_envmap()),
wings_pref:set_default(matcap_texture, def_matcap()),
wings_pref:set_default(matcap_rotate, 0.0),
wings_pref:set_default(matcap_use_diffuse, false),
EnvImgRec = load_env_file(wings_pref:get_value(bg_image)),
init(false, EnvImgRec).

Expand All @@ -69,6 +77,7 @@ init(Recompile) -> %% Debug

init(Recompile, EnvImgRec) ->
AreaMatTagId = load_area_light_tab(),
MatCapTagId = load_matcap_light_tag(),
EnvIds = case wings:is_fast_start() orelse cl_setup(Recompile) of
true ->
fake_envmap(load_env_file(def_envmap()));
Expand All @@ -80,7 +89,7 @@ init(Recompile, EnvImgRec) ->
CL ->
make_envmap(CL, EnvImgRec)
end,
[?SET(Tag, Id) || {Tag,Id} <- [AreaMatTagId|EnvIds]],
[?SET(Tag, Id) || {Tag,Id} <- [AreaMatTagId|EnvIds++MatCapTagId]],
init_opengl(),
wings_develop:gl_error_check({?MODULE,?FUNCTION_NAME}),
ok.
Expand All @@ -106,12 +115,34 @@ load_env_image_1(FileName) ->
wings_develop:gl_error_check({?MODULE,?FUNCTION_NAME}),
ok.

-spec load_matcap_texture(FileName::string()) -> ok | {file_error, {error, term()}}.
load_matcap_texture(FileName) ->
try load_matcap_texture_1(FileName)
catch throw:Error ->
Error
end.

load_matcap_texture_1(FileName) ->
Img = wings_image:image_read([{filename, FileName}]),
is_record(Img, e3d_image) orelse throw({file_error, Img}),
#e3d_image{width=W,height=H}=Img,
if (W=/=H) -> throw({file_error,{error,"Image must be square and sized to a power of two"}});
true -> ok
end,
Res = wings_image:nearest_power_two(W),
{{Tag,Id},_} = make_matcap(Img, Res),
?SET(Tag, Id),
init_opengl(),
wings_develop:gl_error_check({?MODULE,?FUNCTION_NAME}),
ok.

init_opengl() ->
%% Bind textures to units
Ids = [{areamatrix_tex, ?AREA_LTC_MAT_UNIT},
{brdf_tex, ?ENV_BRDF_MAP_UNIT},
{env_diffuse_tex, ?ENV_DIFF_MAP_UNIT},
{env_spec_tex, ?ENV_SPEC_MAP_UNIT}],
{env_spec_tex, ?ENV_SPEC_MAP_UNIT},
{matcap_tex, ?MATCAP_MAP_UNIT}],
SetupUnit = fun({Tag, Unit}) ->
case ?GET(Tag) of
undefined -> ignore;
Expand Down Expand Up @@ -156,7 +187,6 @@ command({duplicate,Dir}, St) ->
duplicate(Dir, St).

-spec is_any_light_selected(#st{}) -> boolean().

is_any_light_selected(St) ->
MF = fun(_, We) -> ?IS_LIGHT(We) end,
RF = fun erlang:'or'/2,
Expand Down Expand Up @@ -644,7 +674,9 @@ export_camera_lights() ->
[{?__(2,"Infinite"),camera_infinite_1_0()}];
2 ->
[{?__(3,"Infinite1"),camera_infinite_2_0()},
{?__(4,"Infinite2"),camera_infinite_2_1()}]
{?__(4,"Infinite2"),camera_infinite_2_1()}];
3 ->
[{?__(2,"Infinite"),camera_infinite_1_0()}]
end,
#view{origin=Aim} = wings_view:current(),
CameraPos = wings_view:eye_point(),
Expand Down Expand Up @@ -1011,6 +1043,16 @@ load_area_light_tab() ->
?CHECK_ERROR(),
{areamatrix_tex, ImId}.

load_matcap_light_tag() ->
FileName = wings_pref:get_value(matcap_texture, def_matcap()),
case load_matcap_texture(FileName) of
ok ->
Id = ?GET(matcap_tex),
[{matcap_tex,Id}];
_ ->
[]
end.

fake_envmap(EnvImgRec) ->
%% Poor mans version with blurred images
Path = filename:join(wings_util:lib_dir(wings), "textures"),
Expand Down Expand Up @@ -1120,6 +1162,13 @@ make_mipmaps(Img, _, _, _) ->
wxImage:destroy(Img),
[].

make_matcap(Img0, Res) ->
Opts = [{wrap, {clamp,clamp}}, {filter, {linear, linear}}],
Img = wings_image:resize_image(Img0#e3d_image{extra=Opts},Res,Res),
%% wings_image:debug_display(matcap,Img#e3d_image{name="MatCap"}),
ImId = wings_image:new_hidden(matcap_tex, Img),
{{matcap_tex, ImId}, Img#e3d_image.image}.

make_envmap(CL, #e3d_image{filename=FileName}=EnvImgRec) ->
EnvIds =
case load_cached_envmap(FileName) of
Expand Down
28 changes: 22 additions & 6 deletions src/wings_menu.erl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
-module(wings_menu).
-export([is_popup_event/1,popup_menu/4,build_command/2,
kill_menus/0, predefined_item/2]).
-export([setup_menus/2, id_to_name/1, check_item/1, str_clean/1]).
-export([setup_menus/2, id_to_name/1, check_item/1, select_item/1, str_clean/1]).
-export([update_menu/3, update_menu/4,
update_menu_enabled/3, update_menu_hotkey/2]).

Expand Down Expand Up @@ -797,6 +797,13 @@ check_item(Name) ->
wxMenuItem:check(MenuItem, [{check, not Checked}])
end.

select_item(Name) ->
case ets:match_object(wings_menus, #menu{name=Name, type=?wxITEM_RADIO, _ = '_'}) of
[] -> ok;
[#menu{object=MenuItem}] -> %% Select the item in a radio group
wxMenuItem:check(MenuItem, [{check, true}])
end.

update_menu(Menu, Item, Cmd) ->
update_menu(Menu, Item, Cmd, undefined).

Expand Down Expand Up @@ -1111,11 +1118,20 @@ menu_item(#menu{desc=Desc0, name=Name, help=Help, opts=Props, hk=HotKey}=ME, Par
false ->
Name
end,
{Type,Check} = case proplists:get_value(crossmark, Props) of
undefined -> {?wxITEM_NORMAL, false};
false -> {?wxITEM_CHECK, false};
_ -> {?wxITEM_CHECK, true} %% grey or true
end,
{Type,Check} =
case proplists:is_defined(crossmark, Props) of
true ->
case proplists:get_value(crossmark, Props) of
false -> {?wxITEM_CHECK, false};
_ -> {?wxITEM_CHECK, true} %% grey or true
end;
false ->
case proplists:get_value(radiomark, Props) of
undefined -> {?wxITEM_NORMAL, false};
false -> {?wxITEM_RADIO, false};
_ -> {?wxITEM_RADIO, true}
end
end,
MI = wxMenuItem:new([{parentMenu, Parent}, {id,MenuId},
{text,Desc}, {kind, Type}, {help,Help}]),
Cmd = case is_function(Command) of
Expand Down
Loading
Loading