EEVEE & Viewport: Add a built-in shader called 3D_IMAGE, and expose to the python API

Adds an example python script to the documentation for the 3D_IMAGE shader.

The **use-case** is to draw textures with 3D vertex positions, in XR views as well as non-XR views (in a simpler manner).

**Testing**: I've tested that this compiles and works on my Macbook (with the example python script included in this change). I don't have access to a Windows or Linux machine right now, but this change doesn't look platform-specific and no new glsl shaders have been added or edited by this change. I'll try to get access to a Windows machine, but if someone does have one, I'd be really grateful if they could try this change. Thanks!

**Problem addressed**: The existing 2D_IMAGE shader (exposed in the python API) gets near-clipped when drawn in the
XR view, regardless of the near-clip settings. Additionally, the 2D_IMAGE shader only accepts 2D
positions for the image vertices, which means drawing textures in 3D requires providing
2D coordinates and then pushing a transform-rotate-scale matrix to the GPU, even for
non-XR (i.e. WINDOW) views. The 3D_IMAGE shader is simpler: it accepts 3D vertex positions, and doesn't require
any additional work by the scripter.

**Workaround**: The current workaround is to use custom shaders in the python script.

**Non-intrusive change**: No new glsl shaders were added. This change just bundles two existing shaders: the vertex shader used
by the 3D_IMAGE_MODULATE_ALPHA shader, and the fragment shader used by the 2D_IMAGE shader.

Reviewed By: #eevee_viewport, jbakker

Differential Revision: https://developer.blender.org/D14832
This commit is contained in:
Shashank Shekhar 2022-05-09 08:07:28 +02:00 committed by Jeroen Bakker
parent 2a2261d7e1
commit 90298c24a2
7 changed files with 74 additions and 0 deletions

View File

@ -29,3 +29,36 @@ def draw():
bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL')
"""
3D Image
--------
Similar to the 2D Image shader, but works with 3D positions for the image vertices.
To use this example you have to provide an image that should be displayed.
"""
import bpy
import gpu
from gpu_extras.batch import batch_for_shader
IMAGE_NAME = "Untitled"
image = bpy.data.images[IMAGE_NAME]
texture = gpu.texture.from_image(image)
shader = gpu.shader.from_builtin('3D_IMAGE')
batch = batch_for_shader(
shader, 'TRIS',
{
"pos": ((0, 0, 0), (0, 1, 1), (1, 1, 1), (1, 1, 1), (1, 0, 0), (0, 0, 0)),
"texCoord": ((0, 0), (0, 1), (1, 1), (1, 1), (1, 0), (0, 0)),
},
)
def draw():
shader.bind()
shader.uniform_sampler("image", texture)
batch.draw(shader)
bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')

View File

@ -498,6 +498,7 @@ set(SRC_SHADER_CREATE_INFOS
shaders/infos/gpu_shader_2D_widget_info.hh
shaders/infos/gpu_shader_3D_depth_only_info.hh
shaders/infos/gpu_shader_3D_flat_color_info.hh
shaders/infos/gpu_shader_3D_image_info.hh
shaders/infos/gpu_shader_3D_image_modulate_alpha_info.hh
shaders/infos/gpu_shader_3D_point_info.hh
shaders/infos/gpu_shader_3D_polyline_info.hh

View File

@ -279,6 +279,16 @@ typedef enum eGPUBuiltinShader {
GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE,
GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE,
GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR,
/**
* Draw a texture in 3D. Take a 3D position and a 2D texture coordinate for each vertex.
*
* Exposed via pyapi for add-ons.
*
* \param image: uniform sampler2D
* \param texCoord: in vec2
* \param pos: in vec3
*/
GPU_SHADER_3D_IMAGE,
/**
* Draw texture with alpha. Take a 3D position and a 2D texture coordinate for each vertex.
*

View File

@ -150,6 +150,11 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.name = "GPU_SHADER_SIMPLE_LIGHTING",
.create_info = "gpu_shader_simple_lighting",
},
[GPU_SHADER_3D_IMAGE] =
{
.name = "GPU_SHADER_3D_IMAGE",
.create_info = "gpu_shader_3D_image",
},
[GPU_SHADER_3D_IMAGE_MODULATE_ALPHA] =
{
.name = "GPU_SHADER_3D_IMAGE_MODULATE_ALPHA",

View File

@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2022 Blender Foundation. All rights reserved. */
/** \file
* \ingroup gpu
*/
#include "gpu_interface_info.hh"
#include "gpu_shader_create_info.hh"
GPU_SHADER_CREATE_INFO(gpu_shader_3D_image)
.vertex_in(0, Type::VEC3, "pos")
.vertex_in(1, Type::VEC2, "texCoord")
.vertex_out(smooth_tex_coord_interp_iface)
.fragment_out(0, Type::VEC4, "fragColor")
.push_constant(Type::MAT4, "ModelViewProjectionMatrix")
.sampler(0, ImageType::FLOAT_2D, "image")
.vertex_source("gpu_shader_3D_image_vert.glsl")
.fragment_source("gpu_shader_image_frag.glsl")
.do_static_compilation(true);

View File

@ -35,6 +35,7 @@ static void test_shader_builtin()
test_compile_builtin_shader(GPU_SHADER_2D_UNIFORM_COLOR, GPU_SHADER_CFG_DEFAULT);
test_compile_builtin_shader(GPU_SHADER_2D_FLAT_COLOR, GPU_SHADER_CFG_DEFAULT);
test_compile_builtin_shader(GPU_SHADER_2D_SMOOTH_COLOR, GPU_SHADER_CFG_DEFAULT);
test_compile_builtin_shader(GPU_SHADER_3D_IMAGE, GPU_SHADER_CFG_DEFAULT);
test_compile_builtin_shader(GPU_SHADER_2D_IMAGE, GPU_SHADER_CFG_DEFAULT);
test_compile_builtin_shader(GPU_SHADER_2D_IMAGE_COLOR, GPU_SHADER_CFG_DEFAULT);
test_compile_builtin_shader(GPU_SHADER_2D_IMAGE_DESATURATE_COLOR, GPU_SHADER_CFG_DEFAULT);

View File

@ -46,6 +46,9 @@
"``3D_FLAT_COLOR``\n" \
" :Attributes: vec3 pos, vec4 color\n" \
" :Uniforms: none\n" \
"``3D_IMAGE``\n" \
" :Attributes: vec3 pos, vec2 texCoord\n" \
" :Uniforms: sampler2D image\n" \
"``3D_SMOOTH_COLOR``\n" \
" :Attributes: vec3 pos, vec4 color\n" \
" :Uniforms: none\n" \
@ -68,6 +71,7 @@ static const struct PyC_StringEnumItems pygpu_shader_builtin_items[] = {
{GPU_SHADER_2D_SMOOTH_COLOR, "2D_SMOOTH_COLOR"},
{GPU_SHADER_2D_UNIFORM_COLOR, "2D_UNIFORM_COLOR"},
{GPU_SHADER_3D_FLAT_COLOR, "3D_FLAT_COLOR"},
{GPU_SHADER_3D_IMAGE, "3D_IMAGE"},
{GPU_SHADER_3D_SMOOTH_COLOR, "3D_SMOOTH_COLOR"},
{GPU_SHADER_3D_UNIFORM_COLOR, "3D_UNIFORM_COLOR"},
{GPU_SHADER_3D_POLYLINE_FLAT_COLOR, "3D_POLYLINE_FLAT_COLOR"},