Skip to content
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

Merge shader create info #424

Merged
merged 5 commits into from
Nov 15, 2023
Merged
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
50 changes: 39 additions & 11 deletions gizmos/preselection.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,45 @@ def test_select(self, context, location):
offscreen = global_data.offscreen
if not offscreen:
return -1
with offscreen.bind():
fb = gpu.state.active_framebuffer_get()
buffer = fb.read_color(mouse_x, mouse_y, 1, 1, 4, 0, "FLOAT")
r, g, b, alpha = buffer[0][0]

if alpha > 0:
index = rgb_to_index(r, g, b)
if index != global_data.hover:
global_data.hover = index
context.area.tag_redraw()
elif global_data.hover != -1:
# TODO: Read buffer only once
PICK_SIZE = 10
for x, y in get_spiral_coords(mouse_x, mouse_y, context.area.width, context.area.height, PICK_SIZE):
with offscreen.bind():
fb = gpu.state.active_framebuffer_get()
buffer = fb.read_color(x, y, 1, 1, 4, 0, "FLOAT")
r, g, b, alpha = buffer[0][0]

if alpha > 0:
index = rgb_to_index(r, g, b)
if index != global_data.hover:
global_data.hover = index
context.area.tag_redraw()
return -1

if global_data.hover != -1:
context.area.tag_redraw()
global_data.hover = -1
return -1


def _spiral(N, M):
x,y = 0,0
dx, dy = 0, -1

for dumb in range(N*M):
if abs(x) == abs(y) and [dx,dy] != [1,0] or x>0 and y == 1-x:
dx, dy = -dy, dx # corner, change direction

if abs(x)>N/2 or abs(y)>M/2: # non-square
dx, dy = -dy, dx # change direction
x, y = -y+dx, x+dy # jump

yield x, y
x, y = x+dx, y+dy

def get_spiral_coords(X: int, Y: int, width: int, height: int, radius: int = 0):
"""Returns a list of coordinates to check starting from given position spiraling out"""

for x, y in _spiral(radius+1,radius+1):
if 0 <= (X+x) <= width and 0 <= (Y+y) <= height:
yield (X+x, Y+y)
16 changes: 7 additions & 9 deletions model/base_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def line_width(self):

@property
def line_width_select(self):
return 20 * preferences.get_scale()
return 4 * preferences.get_scale()

def __str__(self):
_, local_index = breakdown_index(self.slvs_index)
Expand Down Expand Up @@ -230,11 +230,9 @@ def draw(self, context):

if not self.is_point():
shader.uniform_bool("dashed", (self.is_dashed(),))

if not self.is_point():
viewport = [context.area.width, context.area.height]
shader.uniform_float("Viewport", viewport)
shader.uniform_float("thickness", self.line_width)
shader.uniform_float("dash_width", 0.05)
shader.uniform_float("dash_factor", 0.3)
gpu.state.line_width_set(self.line_width)

batch.draw(shader)
gpu.shader.unbind()
Expand All @@ -256,10 +254,10 @@ def draw_id(self, context):

shader.uniform_float("color", (*index_to_rgb(self.slvs_index), 1.0))
if not self.is_point():
viewport = [context.area.width, context.area.height]
shader.uniform_float("Viewport", viewport)
shader.uniform_float("thickness", self.line_width_select)
# viewport = [context.area.width, context.area.height]
# shader.uniform_float("Viewport", viewport)
shader.uniform_bool("dashed", (False,))
gpu.state.line_width_set(self.line_width_select)

batch.draw(shader)
gpu.shader.unbind()
Expand Down
194 changes: 72 additions & 122 deletions shaders.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import gpu
from gpu.types import GPUShader
from gpu.types import GPUShader, GPUShaderCreateInfo, GPUStageInterfaceInfo
from gpu.shader import create_from_info
from bpy import app

import sys
Expand All @@ -16,28 +17,16 @@
class Shaders:

base_vertex_shader_3d = """
uniform mat4 ModelViewProjectionMatrix;

in vec3 pos;

void main() {
gl_Position = ModelViewProjectionMatrix * vec4(pos.xyz, 1.0f);

vec2 ssPos = vec2(gl_Position.xy / gl_Position.w);
stipple_start = stipple_pos = ssPos;
}
"""
base_fragment_shader_3d = """
uniform vec4 color;
uniform float dash_width = 10.0;
uniform float dash_factor = 0.40;
uniform vec2 Viewport;
uniform bool dashed = false;

noperspective in vec2 stipple_pos;
flat in vec2 stipple_start;

out vec4 fragColor;
void main() {

float aspect = Viewport.x/Viewport.y;
float distance_along_line = distance(stipple_pos, stipple_start);
float normalized_distance = fract(distance_along_line / dash_width);

Expand All @@ -56,6 +45,31 @@ class Shaders:
}
"""

@classmethod
def get_base_shader_3d_info(cls):

vert_out = GPUStageInterfaceInfo("stipple_pos_interface")
vert_out.no_perspective("VEC2", "stipple_pos")
vert_out.flat("VEC2", "stipple_start")

# NOTE: How to set default values?

shader_info = GPUShaderCreateInfo()
shader_info.push_constant("MAT4", "ModelViewProjectionMatrix")
shader_info.push_constant("VEC4", "color")
shader_info.push_constant("FLOAT", "dash_width")
shader_info.push_constant("FLOAT", "dash_factor")
# shader_info.push_constant("VEC2", "Viewport")
shader_info.push_constant("BOOL", "dashed")
shader_info.vertex_in(0, "VEC3", "pos")
shader_info.vertex_out(vert_out)
shader_info.fragment_out(0, "VEC4", "fragColor")

shader_info.vertex_source(cls.base_vertex_shader_3d)
shader_info.fragment_source(cls.base_fragment_shader_3d)

return shader_info

@staticmethod
@cache
def uniform_color_3d():
Expand All @@ -66,13 +80,21 @@ def uniform_color_3d():
@classmethod
@cache
def uniform_color_image_2d(cls):
vertex_shader = """
uniform mat4 ModelViewProjectionMatrix;

in vec2 pos;
in vec2 texCoord;
out vec2 v_texCoord;

vert_out = GPUStageInterfaceInfo("uniform_color_image_2d_interface")
vert_out.smooth("VEC2", "v_texCoord")

shader_info = GPUShaderCreateInfo()
shader_info.define("blender_srgb_to_framebuffer_space(a)", "a")
shader_info.push_constant("MAT4", "ModelViewProjectionMatrix")
shader_info.push_constant("VEC4", "color")
shader_info.vertex_in(0, "VEC2", "pos")
shader_info.vertex_in(1, "VEC2", "texCoord")
shader_info.sampler(0, "FLOAT_2D", "image")
shader_info.vertex_out(vert_out)
shader_info.fragment_out(0, "VEC4", "fragColor")

shader_info.vertex_source(
"""
void main()
{
gl_Position = (
Expand All @@ -81,24 +103,23 @@ def uniform_color_image_2d(cls):
v_texCoord = texCoord;
}
"""
fragment_shader = """
uniform vec4 color;
uniform sampler2D image;
in vec2 v_texCoord;
out vec4 fragColor;

)
shader_info.fragment_source(
"""
void main()
{
fragColor = blender_srgb_to_framebuffer_space(
texture(image, v_texCoord) * color
);
}
"""
return GPUShader(
vertex_shader,
fragment_shader,
)

shader = create_from_info(shader_info)
del vert_out
del shader_info
return shader

@classmethod
@cache
def id_line_3d(cls):
Expand All @@ -108,113 +129,42 @@ def id_line_3d(cls):
@classmethod
@cache
def uniform_color_line_3d(cls):
geometry_shader = """
layout(lines) in;
layout(triangle_strip, max_vertices = 10) out;

uniform mat4 ModelViewProjectionMatrix;
uniform vec2 Viewport;
uniform float thickness = float(0.1);

/* We leverage hardware interpolation to compute distance along the line. */
noperspective out vec2 stipple_pos; /* In screen space */
flat out vec2 stipple_start; /* In screen space */

out vec2 mTexCoord;
out float alpha;
float aspect = Viewport.x/Viewport.y;
vec2 pxVec = vec2(1.0/Viewport.x,1.0/Viewport.y);
float minLength = length(pxVec);
vec2 get_line_width(vec2 normal, float width){
vec2 offsetvec = vec2(normal * width);
if (length(offsetvec) < minLength){
offsetvec = normalize(offsetvec);
offsetvec *= minLength;
}
return(offsetvec);
}
float get_line_alpha(vec2 normal, float width){
vec2 offsetvec = vec2(normal * width);
float alpha = 1.0;
if (length(offsetvec) < minLength){
alpha *= (length(offsetvec)/minLength);
}
return alpha;
}
void main() {
//calculate line normal
vec4 p1 = gl_in[0].gl_Position;
vec4 p2 = gl_in[1].gl_Position;
vec2 ssp1 = vec2(p1.xy / p1.w);
vec2 ssp2 = vec2(p2.xy / p2.w);
float width = thickness;
vec2 dir = normalize((ssp2 - ssp1) * Viewport.xy);
vec2 normal = vec2(-dir[1], dir[0]);
normal = normalize(normal);

// get offset factor from normal and user input thickness
vec2 offset = get_line_width(normal,width) / Viewport.xy;
float lineAlpha = get_line_alpha(normal,width);
vec4 coords[4];
vec2 texCoords[4];
coords[0] = vec4((ssp1 + offset)*p1.w,p1.z,p1.w);
texCoords[0] = vec2(0,1);
coords[1] = vec4((ssp1 - offset)*p1.w,p1.z,p1.w);
texCoords[1] = vec2(0,0);
coords[2] = vec4((ssp2 + offset)*p2.w,p2.z,p2.w);
texCoords[2] = vec2(0,1);
coords[3] = vec4((ssp2 - offset)*p2.w,p2.z,p2.w);
texCoords[3] = vec2(0,0);

for (int i = 0; i < 4; ++i) {
mTexCoord = texCoords[i];
gl_Position = coords[i];
alpha = lineAlpha;

vec4 stipple_base;
if (i < 2) {
stipple_base = vec4(ssp1*p1.w,p1.z,p1.w);
}
else {
stipple_base = vec4(ssp2*p2.w, p2.z, p2.w);
}
stipple_start = stipple_pos = Viewport * 0.5 * (stipple_base.xy / stipple_base.w);

EmitVertex();
}
EndPrimitive();
}
"""

return GPUShader(
cls.base_vertex_shader_3d,
cls.base_fragment_shader_3d,
geocode=geometry_shader,
)
shader_info = cls.get_base_shader_3d_info()
shader = create_from_info(shader_info)
del shader_info
return shader

@staticmethod
@cache
def id_shader_3d():
vertex_shader = """
uniform mat4 ModelViewProjectionMatrix;
in vec3 pos;
shader_info = GPUShaderCreateInfo()
shader_info.push_constant("MAT4", "ModelViewProjectionMatrix")
shader_info.push_constant("VEC4", "color")
shader_info.vertex_in(0, "VEC3", "pos")
shader_info.fragment_out(0, "VEC4", "fragColor")

shader_info.vertex_source(
"""
void main()
{
gl_Position = ModelViewProjectionMatrix * vec4(pos, 1.0);
}
"""
)

fragment_shader = """
uniform vec4 color;
out vec4 fragColor;

shader_info.fragment_source(
"""
void main()
{
fragColor = color;
}
"""
return GPUShader(vertex_shader, fragment_shader)
)

shader = create_from_info(shader_info)
del shader_info
return shader

@staticmethod
@cache
Expand Down
Loading