2022-03-21 12:25:25 +01:00
/**************************************************************************/
/* material_storage.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
# ifdef GLES3_ENABLED
2022-02-20 01:08:53 +01:00
# include "core/config/project_settings.h"
2022-03-21 12:25:25 +01:00
# include "config.h"
2022-02-20 01:08:53 +01:00
# include "material_storage.h"
2022-11-08 07:40:03 +01:00
# include "particles_storage.h"
2022-03-21 12:25:25 +01:00
# include "texture_storage.h"
# include "drivers/gles3/rasterizer_canvas_gles3.h"
2023-01-29 10:14:22 +01:00
# include "drivers/gles3/rasterizer_gles3.h"
2023-03-15 07:40:06 +01:00
# include "servers/rendering/storage/variant_converters.h"
2022-03-21 12:25:25 +01:00
using namespace GLES3 ;
2022-02-20 01:08:53 +01:00
///////////////////////////////////////////////////////////////////////////
// UBI helper functions
2023-03-15 07:40:06 +01:00
static void _fill_std140_variant_ubo_value ( ShaderLanguage : : DataType type , int p_array_size , const Variant & value , uint8_t * data ) {
2022-02-20 01:08:53 +01:00
switch ( type ) {
case ShaderLanguage : : TYPE_BOOL : {
uint32_t * gui = ( uint32_t * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
PackedInt32Array ba = value ;
for ( int i = 0 ; i < ba . size ( ) ; i + + ) {
ba . set ( i , ba [ i ] ? 1 : 0 ) ;
2022-02-20 01:08:53 +01:00
}
2023-03-15 07:40:06 +01:00
write_array_std140 < int32_t > ( ba , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
bool v = value ;
gui [ 0 ] = v ? 1 : 0 ;
}
} break ;
case ShaderLanguage : : TYPE_BVEC2 : {
uint32_t * gui = ( uint32_t * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
PackedInt32Array ba = convert_array_std140 < Vector2i , int32_t > ( value ) ;
for ( int i = 0 ; i < ba . size ( ) ; i + + ) {
ba . set ( i , ba [ i ] ? 1 : 0 ) ;
2022-02-20 01:08:53 +01:00
}
2023-03-15 07:40:06 +01:00
write_array_std140 < Vector2i > ( ba , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
2022-10-09 07:14:07 +02:00
uint32_t v = value ;
2022-02-20 01:08:53 +01:00
gui [ 0 ] = v & 1 ? 1 : 0 ;
gui [ 1 ] = v & 2 ? 1 : 0 ;
}
} break ;
case ShaderLanguage : : TYPE_BVEC3 : {
uint32_t * gui = ( uint32_t * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
PackedInt32Array ba = convert_array_std140 < Vector3i , int32_t > ( value ) ;
for ( int i = 0 ; i < ba . size ( ) ; i + + ) {
ba . set ( i , ba [ i ] ? 1 : 0 ) ;
2022-02-20 01:08:53 +01:00
}
2023-03-15 07:40:06 +01:00
write_array_std140 < Vector3i > ( ba , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
2022-10-09 07:14:07 +02:00
uint32_t v = value ;
2022-02-20 01:08:53 +01:00
gui [ 0 ] = ( v & 1 ) ? 1 : 0 ;
gui [ 1 ] = ( v & 2 ) ? 1 : 0 ;
gui [ 2 ] = ( v & 4 ) ? 1 : 0 ;
}
} break ;
case ShaderLanguage : : TYPE_BVEC4 : {
uint32_t * gui = ( uint32_t * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
PackedInt32Array ba = convert_array_std140 < Vector4i , int32_t > ( value ) ;
for ( int i = 0 ; i < ba . size ( ) ; i + + ) {
ba . set ( i , ba [ i ] ? 1 : 0 ) ;
2022-02-20 01:08:53 +01:00
}
2023-03-15 07:40:06 +01:00
write_array_std140 < Vector4i > ( ba , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
2022-10-09 07:14:07 +02:00
uint32_t v = value ;
2022-02-20 01:08:53 +01:00
gui [ 0 ] = ( v & 1 ) ? 1 : 0 ;
gui [ 1 ] = ( v & 2 ) ? 1 : 0 ;
gui [ 2 ] = ( v & 4 ) ? 1 : 0 ;
gui [ 3 ] = ( v & 8 ) ? 1 : 0 ;
}
} break ;
case ShaderLanguage : : TYPE_INT : {
int32_t * gui = ( int32_t * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedInt32Array & iv = value ;
write_array_std140 < int32_t > ( iv , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
int v = value ;
gui [ 0 ] = v ;
}
} break ;
case ShaderLanguage : : TYPE_IVEC2 : {
int32_t * gui = ( int32_t * ) data ;
2023-03-15 07:40:06 +01:00
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedInt32Array & iv = convert_array_std140 < Vector2i , int32_t > ( value ) ;
write_array_std140 < Vector2i > ( iv , gui , p_array_size , 4 ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
} else {
2023-03-15 07:40:06 +01:00
Vector2i v = convert_to_vector < Vector2i > ( value ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
2022-02-20 01:08:53 +01:00
}
} break ;
case ShaderLanguage : : TYPE_IVEC3 : {
int32_t * gui = ( int32_t * ) data ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedInt32Array & iv = convert_array_std140 < Vector3i , int32_t > ( value ) ;
write_array_std140 < Vector3i > ( iv , gui , p_array_size , 4 ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
} else {
2023-03-15 07:40:06 +01:00
Vector3i v = convert_to_vector < Vector3i > ( value ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
gui [ 2 ] = v . z ;
2022-02-20 01:08:53 +01:00
}
} break ;
case ShaderLanguage : : TYPE_IVEC4 : {
int32_t * gui = ( int32_t * ) data ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedInt32Array & iv = convert_array_std140 < Vector4i , int32_t > ( value ) ;
write_array_std140 < Vector4i > ( iv , gui , p_array_size , 4 ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
} else {
2023-03-15 07:40:06 +01:00
Vector4i v = convert_to_vector < Vector4i > ( value ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
gui [ 2 ] = v . z ;
gui [ 3 ] = v . w ;
2022-02-20 01:08:53 +01:00
}
} break ;
case ShaderLanguage : : TYPE_UINT : {
uint32_t * gui = ( uint32_t * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedInt32Array & iv = value ;
write_array_std140 < uint32_t > ( iv , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
int v = value ;
gui [ 0 ] = v ;
}
} break ;
case ShaderLanguage : : TYPE_UVEC2 : {
uint32_t * gui = ( uint32_t * ) data ;
2023-03-15 07:40:06 +01:00
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedInt32Array & iv = convert_array_std140 < Vector2i , int32_t > ( value ) ;
write_array_std140 < Vector2i > ( iv , gui , p_array_size , 4 ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
} else {
2023-03-15 07:40:06 +01:00
Vector2i v = convert_to_vector < Vector2i > ( value ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
2022-02-20 01:08:53 +01:00
}
} break ;
case ShaderLanguage : : TYPE_UVEC3 : {
uint32_t * gui = ( uint32_t * ) data ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedInt32Array & iv = convert_array_std140 < Vector3i , int32_t > ( value ) ;
write_array_std140 < Vector3i > ( iv , gui , p_array_size , 4 ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
} else {
2023-03-15 07:40:06 +01:00
Vector3i v = convert_to_vector < Vector3i > ( value ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
gui [ 2 ] = v . z ;
2022-02-20 01:08:53 +01:00
}
} break ;
case ShaderLanguage : : TYPE_UVEC4 : {
uint32_t * gui = ( uint32_t * ) data ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedInt32Array & iv = convert_array_std140 < Vector4i , int32_t > ( value ) ;
write_array_std140 < Vector4i > ( iv , gui , p_array_size , 4 ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
} else {
2023-03-15 07:40:06 +01:00
Vector4i v = convert_to_vector < Vector4i > ( value ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
gui [ 2 ] = v . z ;
gui [ 3 ] = v . w ;
2022-02-20 01:08:53 +01:00
}
} break ;
case ShaderLanguage : : TYPE_FLOAT : {
float * gui = ( float * ) data ;
if ( p_array_size > 0 ) {
const PackedFloat32Array & a = value ;
2023-03-15 07:40:06 +01:00
write_array_std140 < float > ( a , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
float v = value ;
gui [ 0 ] = v ;
}
} break ;
case ShaderLanguage : : TYPE_VEC2 : {
float * gui = ( float * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedFloat32Array & a = convert_array_std140 < Vector2 , float > ( value ) ;
write_array_std140 < Vector2 > ( a , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
2023-03-15 07:40:06 +01:00
Vector2 v = convert_to_vector < Vector2 > ( value ) ;
2022-02-20 01:08:53 +01:00
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
}
} break ;
case ShaderLanguage : : TYPE_VEC3 : {
float * gui = ( float * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedFloat32Array & a = convert_array_std140 < Vector3 , float > ( value ) ;
write_array_std140 < Vector3 > ( a , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
2023-03-15 07:40:06 +01:00
Vector3 v = convert_to_vector < Vector3 > ( value ) ;
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
gui [ 2 ] = v . z ;
2022-02-20 01:08:53 +01:00
}
} break ;
case ShaderLanguage : : TYPE_VEC4 : {
float * gui = ( float * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedFloat32Array & a = convert_array_std140 < Vector4 , float > ( value ) ;
write_array_std140 < Vector4 > ( a , gui , p_array_size , 4 ) ;
2022-02-20 01:08:53 +01:00
} else {
2023-03-15 07:40:06 +01:00
Vector4 v = convert_to_vector < Vector4 > ( value ) ;
gui [ 0 ] = v . x ;
gui [ 1 ] = v . y ;
gui [ 2 ] = v . z ;
gui [ 3 ] = v . w ;
2022-02-20 01:08:53 +01:00
}
} break ;
case ShaderLanguage : : TYPE_MAT2 : {
float * gui = ( float * ) data ;
if ( p_array_size > 0 ) {
const PackedFloat32Array & a = value ;
int s = a . size ( ) ;
for ( int i = 0 , j = 0 ; i < p_array_size * 4 ; i + = 4 , j + = 8 ) {
if ( i + 3 < s ) {
gui [ j ] = a [ i ] ;
gui [ j + 1 ] = a [ i + 1 ] ;
gui [ j + 4 ] = a [ i + 2 ] ;
gui [ j + 5 ] = a [ i + 3 ] ;
} else {
gui [ j ] = 1 ;
gui [ j + 1 ] = 0 ;
gui [ j + 4 ] = 0 ;
gui [ j + 5 ] = 1 ;
}
gui [ j + 2 ] = 0 ; // ignored
gui [ j + 3 ] = 0 ; // ignored
gui [ j + 6 ] = 0 ; // ignored
gui [ j + 7 ] = 0 ; // ignored
}
} else {
Transform2D v = value ;
//in std140 members of mat2 are treated as vec4s
2022-04-24 23:59:24 +02:00
gui [ 0 ] = v . columns [ 0 ] [ 0 ] ;
gui [ 1 ] = v . columns [ 0 ] [ 1 ] ;
2022-02-20 01:08:53 +01:00
gui [ 2 ] = 0 ; // ignored
gui [ 3 ] = 0 ; // ignored
2022-04-24 23:59:24 +02:00
gui [ 4 ] = v . columns [ 1 ] [ 0 ] ;
gui [ 5 ] = v . columns [ 1 ] [ 1 ] ;
2022-02-20 01:08:53 +01:00
gui [ 6 ] = 0 ; // ignored
gui [ 7 ] = 0 ; // ignored
}
} break ;
case ShaderLanguage : : TYPE_MAT3 : {
float * gui = ( float * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedFloat32Array & a = convert_array_std140 < Basis , float > ( value ) ;
const Basis default_basis ;
const int s = a . size ( ) ;
2022-02-20 01:08:53 +01:00
for ( int i = 0 , j = 0 ; i < p_array_size * 9 ; i + = 9 , j + = 12 ) {
if ( i + 8 < s ) {
gui [ j ] = a [ i ] ;
gui [ j + 1 ] = a [ i + 1 ] ;
gui [ j + 2 ] = a [ i + 2 ] ;
2023-03-15 07:40:06 +01:00
gui [ j + 3 ] = 0 ; // Ignored.
2022-02-20 01:08:53 +01:00
gui [ j + 4 ] = a [ i + 3 ] ;
gui [ j + 5 ] = a [ i + 4 ] ;
gui [ j + 6 ] = a [ i + 5 ] ;
2023-03-15 07:40:06 +01:00
gui [ j + 7 ] = 0 ; // Ignored.
2022-02-20 01:08:53 +01:00
gui [ j + 8 ] = a [ i + 6 ] ;
gui [ j + 9 ] = a [ i + 7 ] ;
gui [ j + 10 ] = a [ i + 8 ] ;
2023-03-15 07:40:06 +01:00
gui [ j + 11 ] = 0 ; // Ignored.
2022-02-20 01:08:53 +01:00
} else {
2023-03-15 07:40:06 +01:00
convert_item_std140 ( default_basis , gui + j ) ;
2022-02-20 01:08:53 +01:00
}
}
} else {
2023-03-15 07:40:06 +01:00
convert_item_std140 < Basis > ( value , gui ) ;
2022-02-20 01:08:53 +01:00
}
} break ;
case ShaderLanguage : : TYPE_MAT4 : {
float * gui = ( float * ) data ;
if ( p_array_size > 0 ) {
2023-03-15 07:40:06 +01:00
const PackedFloat32Array & a = convert_array_std140 < Projection , float > ( value ) ;
write_array_std140 < Projection > ( a , gui , p_array_size , 16 ) ;
Implement Vector4, Vector4i, Projection
Implement built-in classes Vector4, Vector4i and Projection.
* Two versions of Vector4 (float and integer).
* A Projection class, which is a 4x4 matrix specialized in projection types.
These types have been requested for a long time, but given they were very corner case they were not added before.
Because in Godot 4, reimplementing parts of the rendering engine is now possible, access to these types (heavily used by the rendering code) becomes a necessity.
**Q**: Why Projection and not Matrix4?
**A**: Godot does not use Matrix2, Matrix3, Matrix4x3, etc. naming convention because, within the engine, these types always have a *purpose*. As such, Godot names them: Transform2D, Transform3D or Basis. In this case, this 4x4 matrix is _always_ used as a _Projection_, hence the naming.
2022-07-20 01:11:13 +02:00
} else {
2023-03-15 07:40:06 +01:00
convert_item_std140 < Projection > ( value , gui ) ;
2022-02-20 01:08:53 +01:00
}
} break ;
default : {
}
}
}
_FORCE_INLINE_ static void _fill_std140_ubo_value ( ShaderLanguage : : DataType type , const Vector < ShaderLanguage : : ConstantNode : : Value > & value , uint8_t * data ) {
switch ( type ) {
case ShaderLanguage : : TYPE_BOOL : {
uint32_t * gui = ( uint32_t * ) data ;
2022-10-09 07:14:07 +02:00
gui [ 0 ] = value [ 0 ] . boolean ? 1 : 0 ;
2022-02-20 01:08:53 +01:00
} break ;
case ShaderLanguage : : TYPE_BVEC2 : {
uint32_t * gui = ( uint32_t * ) data ;
gui [ 0 ] = value [ 0 ] . boolean ? 1 : 0 ;
gui [ 1 ] = value [ 1 ] . boolean ? 1 : 0 ;
} break ;
case ShaderLanguage : : TYPE_BVEC3 : {
uint32_t * gui = ( uint32_t * ) data ;
gui [ 0 ] = value [ 0 ] . boolean ? 1 : 0 ;
gui [ 1 ] = value [ 1 ] . boolean ? 1 : 0 ;
gui [ 2 ] = value [ 2 ] . boolean ? 1 : 0 ;
} break ;
case ShaderLanguage : : TYPE_BVEC4 : {
uint32_t * gui = ( uint32_t * ) data ;
gui [ 0 ] = value [ 0 ] . boolean ? 1 : 0 ;
gui [ 1 ] = value [ 1 ] . boolean ? 1 : 0 ;
gui [ 2 ] = value [ 2 ] . boolean ? 1 : 0 ;
gui [ 3 ] = value [ 3 ] . boolean ? 1 : 0 ;
} break ;
case ShaderLanguage : : TYPE_INT : {
int32_t * gui = ( int32_t * ) data ;
gui [ 0 ] = value [ 0 ] . sint ;
} break ;
case ShaderLanguage : : TYPE_IVEC2 : {
int32_t * gui = ( int32_t * ) data ;
for ( int i = 0 ; i < 2 ; i + + ) {
gui [ i ] = value [ i ] . sint ;
}
} break ;
case ShaderLanguage : : TYPE_IVEC3 : {
int32_t * gui = ( int32_t * ) data ;
for ( int i = 0 ; i < 3 ; i + + ) {
gui [ i ] = value [ i ] . sint ;
}
} break ;
case ShaderLanguage : : TYPE_IVEC4 : {
int32_t * gui = ( int32_t * ) data ;
for ( int i = 0 ; i < 4 ; i + + ) {
gui [ i ] = value [ i ] . sint ;
}
} break ;
case ShaderLanguage : : TYPE_UINT : {
uint32_t * gui = ( uint32_t * ) data ;
gui [ 0 ] = value [ 0 ] . uint ;
} break ;
case ShaderLanguage : : TYPE_UVEC2 : {
int32_t * gui = ( int32_t * ) data ;
for ( int i = 0 ; i < 2 ; i + + ) {
gui [ i ] = value [ i ] . uint ;
}
} break ;
case ShaderLanguage : : TYPE_UVEC3 : {
int32_t * gui = ( int32_t * ) data ;
for ( int i = 0 ; i < 3 ; i + + ) {
gui [ i ] = value [ i ] . uint ;
}
} break ;
case ShaderLanguage : : TYPE_UVEC4 : {
int32_t * gui = ( int32_t * ) data ;
for ( int i = 0 ; i < 4 ; i + + ) {
gui [ i ] = value [ i ] . uint ;
}
} break ;
case ShaderLanguage : : TYPE_FLOAT : {
float * gui = ( float * ) data ;
gui [ 0 ] = value [ 0 ] . real ;
} break ;
case ShaderLanguage : : TYPE_VEC2 : {
float * gui = ( float * ) data ;
for ( int i = 0 ; i < 2 ; i + + ) {
gui [ i ] = value [ i ] . real ;
}
} break ;
case ShaderLanguage : : TYPE_VEC3 : {
float * gui = ( float * ) data ;
for ( int i = 0 ; i < 3 ; i + + ) {
gui [ i ] = value [ i ] . real ;
}
} break ;
case ShaderLanguage : : TYPE_VEC4 : {
float * gui = ( float * ) data ;
for ( int i = 0 ; i < 4 ; i + + ) {
gui [ i ] = value [ i ] . real ;
}
} break ;
case ShaderLanguage : : TYPE_MAT2 : {
float * gui = ( float * ) data ;
//in std140 members of mat2 are treated as vec4s
gui [ 0 ] = value [ 0 ] . real ;
gui [ 1 ] = value [ 1 ] . real ;
gui [ 2 ] = 0 ;
gui [ 3 ] = 0 ;
gui [ 4 ] = value [ 2 ] . real ;
gui [ 5 ] = value [ 3 ] . real ;
gui [ 6 ] = 0 ;
gui [ 7 ] = 0 ;
} break ;
case ShaderLanguage : : TYPE_MAT3 : {
float * gui = ( float * ) data ;
gui [ 0 ] = value [ 0 ] . real ;
gui [ 1 ] = value [ 1 ] . real ;
gui [ 2 ] = value [ 2 ] . real ;
gui [ 3 ] = 0 ;
gui [ 4 ] = value [ 3 ] . real ;
gui [ 5 ] = value [ 4 ] . real ;
gui [ 6 ] = value [ 5 ] . real ;
gui [ 7 ] = 0 ;
gui [ 8 ] = value [ 6 ] . real ;
gui [ 9 ] = value [ 7 ] . real ;
gui [ 10 ] = value [ 8 ] . real ;
gui [ 11 ] = 0 ;
} break ;
case ShaderLanguage : : TYPE_MAT4 : {
float * gui = ( float * ) data ;
for ( int i = 0 ; i < 16 ; i + + ) {
gui [ i ] = value [ i ] . real ;
}
} break ;
default : {
}
}
}
_FORCE_INLINE_ static void _fill_std140_ubo_empty ( ShaderLanguage : : DataType type , int p_array_size , uint8_t * data ) {
if ( p_array_size < = 0 ) {
p_array_size = 1 ;
}
switch ( type ) {
case ShaderLanguage : : TYPE_BOOL :
case ShaderLanguage : : TYPE_INT :
case ShaderLanguage : : TYPE_UINT :
case ShaderLanguage : : TYPE_FLOAT : {
memset ( data , 0 , 4 * p_array_size ) ;
} break ;
case ShaderLanguage : : TYPE_BVEC2 :
case ShaderLanguage : : TYPE_IVEC2 :
case ShaderLanguage : : TYPE_UVEC2 :
case ShaderLanguage : : TYPE_VEC2 : {
memset ( data , 0 , 8 * p_array_size ) ;
} break ;
case ShaderLanguage : : TYPE_BVEC3 :
case ShaderLanguage : : TYPE_IVEC3 :
case ShaderLanguage : : TYPE_UVEC3 :
2022-10-09 05:32:50 +02:00
case ShaderLanguage : : TYPE_VEC3 : {
memset ( data , 0 , 12 * p_array_size ) ;
} break ;
2022-02-20 01:08:53 +01:00
case ShaderLanguage : : TYPE_BVEC4 :
case ShaderLanguage : : TYPE_IVEC4 :
case ShaderLanguage : : TYPE_UVEC4 :
case ShaderLanguage : : TYPE_VEC4 : {
memset ( data , 0 , 16 * p_array_size ) ;
} break ;
case ShaderLanguage : : TYPE_MAT2 : {
memset ( data , 0 , 32 * p_array_size ) ;
} break ;
case ShaderLanguage : : TYPE_MAT3 : {
memset ( data , 0 , 48 * p_array_size ) ;
} break ;
case ShaderLanguage : : TYPE_MAT4 : {
memset ( data , 0 , 64 * p_array_size ) ;
} break ;
default : {
}
}
}
2022-12-13 13:39:53 +01:00
///////////////////////////////////////////////////////////////////////////
// ShaderData
void ShaderData : : set_path_hint ( const String & p_hint ) {
path = p_hint ;
}
void ShaderData : : set_default_texture_parameter ( const StringName & p_name , RID p_texture , int p_index ) {
if ( ! p_texture . is_valid ( ) ) {
if ( default_texture_params . has ( p_name ) & & default_texture_params [ p_name ] . has ( p_index ) ) {
default_texture_params [ p_name ] . erase ( p_index ) ;
if ( default_texture_params [ p_name ] . is_empty ( ) ) {
default_texture_params . erase ( p_name ) ;
}
}
} else {
if ( ! default_texture_params . has ( p_name ) ) {
default_texture_params [ p_name ] = HashMap < int , RID > ( ) ;
}
default_texture_params [ p_name ] [ p_index ] = p_texture ;
}
}
Variant ShaderData : : get_default_parameter ( const StringName & p_parameter ) const {
if ( uniforms . has ( p_parameter ) ) {
ShaderLanguage : : ShaderNode : : Uniform uniform = uniforms [ p_parameter ] ;
Vector < ShaderLanguage : : ConstantNode : : Value > default_value = uniform . default_value ;
return ShaderLanguage : : constant_value_to_variant ( default_value , uniform . type , uniform . array_size , uniform . hint ) ;
}
return Variant ( ) ;
}
void ShaderData : : get_shader_uniform_list ( List < PropertyInfo > * p_param_list ) const {
SortArray < Pair < StringName , int > , ShaderLanguage : : UniformOrderComparator > sorter ;
LocalVector < Pair < StringName , int > > filtered_uniforms ;
for ( const KeyValue < StringName , ShaderLanguage : : ShaderNode : : Uniform > & E : uniforms ) {
if ( E . value . scope ! = ShaderLanguage : : ShaderNode : : Uniform : : SCOPE_LOCAL ) {
continue ;
}
2024-07-26 11:19:13 +02:00
filtered_uniforms . push_back ( Pair < StringName , int > ( E . key , E . value . prop_order ) ) ;
2022-12-13 13:39:53 +01:00
}
int uniform_count = filtered_uniforms . size ( ) ;
sorter . sort ( filtered_uniforms . ptr ( ) , uniform_count ) ;
String last_group ;
for ( int i = 0 ; i < uniform_count ; i + + ) {
const StringName & uniform_name = filtered_uniforms [ i ] . first ;
const ShaderLanguage : : ShaderNode : : Uniform & uniform = uniforms [ uniform_name ] ;
String group = uniform . group ;
if ( ! uniform . subgroup . is_empty ( ) ) {
group + = " :: " + uniform . subgroup ;
}
if ( group ! = last_group ) {
PropertyInfo pi ;
pi . usage = PROPERTY_USAGE_GROUP ;
pi . name = group ;
p_param_list - > push_back ( pi ) ;
last_group = group ;
}
PropertyInfo pi = ShaderLanguage : : uniform_to_property_info ( uniform ) ;
pi . name = uniform_name ;
p_param_list - > push_back ( pi ) ;
}
}
void ShaderData : : get_instance_param_list ( List < RendererMaterialStorage : : InstanceShaderParam > * p_param_list ) const {
for ( const KeyValue < StringName , ShaderLanguage : : ShaderNode : : Uniform > & E : uniforms ) {
if ( E . value . scope ! = ShaderLanguage : : ShaderNode : : Uniform : : SCOPE_INSTANCE ) {
continue ;
}
RendererMaterialStorage : : InstanceShaderParam p ;
p . info = ShaderLanguage : : uniform_to_property_info ( E . value ) ;
p . info . name = E . key ; //supply name
p . index = E . value . instance_index ;
p . default_value = ShaderLanguage : : constant_value_to_variant ( E . value . default_value , E . value . type , E . value . array_size , E . value . hint ) ;
p_param_list - > push_back ( p ) ;
}
}
bool ShaderData : : is_parameter_texture ( const StringName & p_param ) const {
if ( ! uniforms . has ( p_param ) ) {
return false ;
}
2024-07-26 11:19:13 +02:00
return uniforms [ p_param ] . is_texture ( ) ;
2022-12-13 13:39:53 +01:00
}
2022-02-20 01:08:53 +01:00
///////////////////////////////////////////////////////////////////////////
// MaterialData
2022-05-03 22:28:15 +02:00
// Look up table to translate ShaderLanguage::DataType to GL_TEXTURE_*
static const GLenum target_from_type [ ShaderLanguage : : TYPE_MAX ] = {
GL_TEXTURE_2D , // TYPE_VOID,
GL_TEXTURE_2D , // TYPE_BOOL,
GL_TEXTURE_2D , // TYPE_BVEC2,
GL_TEXTURE_2D , // TYPE_BVEC3,
GL_TEXTURE_2D , // TYPE_BVEC4,
GL_TEXTURE_2D , // TYPE_INT,
GL_TEXTURE_2D , // TYPE_IVEC2,
GL_TEXTURE_2D , // TYPE_IVEC3,
GL_TEXTURE_2D , // TYPE_IVEC4,
GL_TEXTURE_2D , // TYPE_UINT,
GL_TEXTURE_2D , // TYPE_UVEC2,
GL_TEXTURE_2D , // TYPE_UVEC3,
GL_TEXTURE_2D , // TYPE_UVEC4,
GL_TEXTURE_2D , // TYPE_FLOAT,
GL_TEXTURE_2D , // TYPE_VEC2,
GL_TEXTURE_2D , // TYPE_VEC3,
GL_TEXTURE_2D , // TYPE_VEC4,
GL_TEXTURE_2D , // TYPE_MAT2,
GL_TEXTURE_2D , // TYPE_MAT3,
GL_TEXTURE_2D , // TYPE_MAT4,
GL_TEXTURE_2D , // TYPE_SAMPLER2D,
GL_TEXTURE_2D , // TYPE_ISAMPLER2D,
GL_TEXTURE_2D , // TYPE_USAMPLER2D,
GL_TEXTURE_2D_ARRAY , // TYPE_SAMPLER2DARRAY,
GL_TEXTURE_2D_ARRAY , // TYPE_ISAMPLER2DARRAY,
GL_TEXTURE_2D_ARRAY , // TYPE_USAMPLER2DARRAY,
GL_TEXTURE_3D , // TYPE_SAMPLER3D,
GL_TEXTURE_3D , // TYPE_ISAMPLER3D,
GL_TEXTURE_3D , // TYPE_USAMPLER3D,
GL_TEXTURE_CUBE_MAP , // TYPE_SAMPLERCUBE,
GL_TEXTURE_CUBE_MAP , // TYPE_SAMPLERCUBEARRAY,
GL_TEXTURE_2D , // TYPE_STRUCT
} ;
2023-01-07 00:52:12 +01:00
static const RS : : CanvasItemTextureRepeat repeat_from_uniform [ ShaderLanguage : : REPEAT_DEFAULT + 1 ] = {
RS : : CanvasItemTextureRepeat : : CANVAS_ITEM_TEXTURE_REPEAT_DISABLED , // ShaderLanguage::TextureRepeat::REPEAT_DISABLE,
RS : : CanvasItemTextureRepeat : : CANVAS_ITEM_TEXTURE_REPEAT_ENABLED , // ShaderLanguage::TextureRepeat::REPEAT_ENABLE,
RS : : CanvasItemTextureRepeat : : CANVAS_ITEM_TEXTURE_REPEAT_ENABLED , // ShaderLanguage::TextureRepeat::REPEAT_DEFAULT,
} ;
2023-03-03 19:58:57 +01:00
static const RS : : CanvasItemTextureRepeat repeat_from_uniform_canvas [ ShaderLanguage : : REPEAT_DEFAULT + 1 ] = {
RS : : CanvasItemTextureRepeat : : CANVAS_ITEM_TEXTURE_REPEAT_DISABLED , // ShaderLanguage::TextureRepeat::REPEAT_DISABLE,
RS : : CanvasItemTextureRepeat : : CANVAS_ITEM_TEXTURE_REPEAT_ENABLED , // ShaderLanguage::TextureRepeat::REPEAT_ENABLE,
RS : : CanvasItemTextureRepeat : : CANVAS_ITEM_TEXTURE_REPEAT_DISABLED , // ShaderLanguage::TextureRepeat::REPEAT_DEFAULT,
} ;
2023-01-07 00:52:12 +01:00
static const RS : : CanvasItemTextureFilter filter_from_uniform [ ShaderLanguage : : FILTER_DEFAULT + 1 ] = {
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_NEAREST , // ShaderLanguage::TextureFilter::FILTER_NEAREST,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_LINEAR , // ShaderLanguage::TextureFilter::FILTER_LINEAR,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS , // ShaderLanguage::TextureFilter::FILTER_NEAREST_MIPMAP,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS , // ShaderLanguage::TextureFilter::FILTER_LINEAR_MIPMAP,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC , // ShaderLanguage::TextureFilter::FILTER_NEAREST_MIPMAP_ANISOTROPIC,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC , // ShaderLanguage::TextureFilter::FILTER_LINEAR_MIPMAP_ANISOTROPIC,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS , // ShaderLanguage::TextureFilter::FILTER_DEFAULT,
} ;
2023-03-03 19:58:57 +01:00
static const RS : : CanvasItemTextureFilter filter_from_uniform_canvas [ ShaderLanguage : : FILTER_DEFAULT + 1 ] = {
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_NEAREST , // ShaderLanguage::TextureFilter::FILTER_NEAREST,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_LINEAR , // ShaderLanguage::TextureFilter::FILTER_LINEAR,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS , // ShaderLanguage::TextureFilter::FILTER_NEAREST_MIPMAP,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS , // ShaderLanguage::TextureFilter::FILTER_LINEAR_MIPMAP,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC , // ShaderLanguage::TextureFilter::FILTER_NEAREST_MIPMAP_ANISOTROPIC,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC , // ShaderLanguage::TextureFilter::FILTER_LINEAR_MIPMAP_ANISOTROPIC,
RS : : CanvasItemTextureFilter : : CANVAS_ITEM_TEXTURE_FILTER_LINEAR , // ShaderLanguage::TextureFilter::FILTER_DEFAULT,
} ;
2023-06-13 22:20:11 +02:00
void MaterialData : : update_uniform_buffer ( const HashMap < StringName , ShaderLanguage : : ShaderNode : : Uniform > & p_uniforms , const uint32_t * p_uniform_offsets , const HashMap < StringName , Variant > & p_parameters , uint8_t * p_buffer , uint32_t p_buffer_size ) {
2022-02-20 01:08:53 +01:00
MaterialStorage * material_storage = MaterialStorage : : get_singleton ( ) ;
bool uses_global_buffer = false ;
for ( const KeyValue < StringName , ShaderLanguage : : ShaderNode : : Uniform > & E : p_uniforms ) {
2024-07-26 11:19:13 +02:00
if ( E . value . is_texture ( ) ) {
2022-02-20 01:08:53 +01:00
continue ; // texture, does not go here
}
if ( E . value . scope = = ShaderLanguage : : ShaderNode : : Uniform : : SCOPE_INSTANCE ) {
continue ; //instance uniforms don't appear in the buffer
}
if ( E . value . scope = = ShaderLanguage : : ShaderNode : : Uniform : : SCOPE_GLOBAL ) {
//this is a global variable, get the index to it
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Variable * gv = material_storage - > global_shader_uniforms . variables . getptr ( E . key ) ;
2022-02-20 01:08:53 +01:00
uint32_t index = 0 ;
if ( gv ) {
index = gv - > buffer_index ;
} else {
2022-08-27 11:22:43 +02:00
WARN_PRINT ( " Shader uses global parameter ' " + E . key + " ', but it was removed at some point. Material will not display correctly. " ) ;
2022-02-20 01:08:53 +01:00
}
uint32_t offset = p_uniform_offsets [ E . value . order ] ;
uint32_t * intptr = ( uint32_t * ) & p_buffer [ offset ] ;
* intptr = index ;
uses_global_buffer = true ;
continue ;
}
//regular uniform
uint32_t offset = p_uniform_offsets [ E . value . order ] ;
# ifdef DEBUG_ENABLED
uint32_t size = 0U ;
// The following code enforces a 16-byte alignment of uniform arrays.
if ( E . value . array_size > 0 ) {
size = ShaderLanguage : : get_datatype_size ( E . value . type ) * E . value . array_size ;
int m = ( 16 * E . value . array_size ) ;
if ( ( size % m ) ! = 0U ) {
size + = m - ( size % m ) ;
}
} else {
size = ShaderLanguage : : get_datatype_size ( E . value . type ) ;
}
ERR_CONTINUE ( offset + size > p_buffer_size ) ;
# endif
uint8_t * data = & p_buffer [ offset ] ;
2022-05-13 15:04:37 +02:00
HashMap < StringName , Variant > : : ConstIterator V = p_parameters . find ( E . key ) ;
2022-02-20 01:08:53 +01:00
if ( V ) {
//user provided
2022-05-13 15:04:37 +02:00
_fill_std140_variant_ubo_value ( E . value . type , E . value . array_size , V - > value , data ) ;
2022-02-20 01:08:53 +01:00
} else if ( E . value . default_value . size ( ) ) {
//default value
_fill_std140_ubo_value ( E . value . type , E . value . default_value , data ) ;
//value=E.value.default_value;
} else {
//zero because it was not provided
2022-05-05 20:23:40 +02:00
if ( ( E . value . type = = ShaderLanguage : : TYPE_VEC3 | | E . value . type = = ShaderLanguage : : TYPE_VEC4 ) & & E . value . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_SOURCE_COLOR ) {
2022-02-20 01:08:53 +01:00
//colors must be set as black, with alpha as 1.0
2022-05-10 19:02:44 +02:00
_fill_std140_variant_ubo_value ( E . value . type , E . value . array_size , Color ( 0 , 0 , 0 , 1 ) , data ) ;
2022-02-20 01:08:53 +01:00
} else {
//else just zero it out
_fill_std140_ubo_empty ( E . value . type , E . value . array_size , data ) ;
}
}
}
if ( uses_global_buffer ! = ( global_buffer_E ! = nullptr ) ) {
if ( uses_global_buffer ) {
2022-04-03 18:56:43 +02:00
global_buffer_E = material_storage - > global_shader_uniforms . materials_using_buffer . push_back ( self ) ;
2022-02-20 01:08:53 +01:00
} else {
2022-04-03 18:56:43 +02:00
material_storage - > global_shader_uniforms . materials_using_buffer . erase ( global_buffer_E ) ;
2022-02-20 01:08:53 +01:00
global_buffer_E = nullptr ;
}
}
}
MaterialData : : ~ MaterialData ( ) {
MaterialStorage * material_storage = MaterialStorage : : get_singleton ( ) ;
if ( global_buffer_E ) {
//unregister global buffers
2022-04-03 18:56:43 +02:00
material_storage - > global_shader_uniforms . materials_using_buffer . erase ( global_buffer_E ) ;
2022-02-20 01:08:53 +01:00
}
if ( global_texture_E ) {
//unregister global textures
for ( const KeyValue < StringName , uint64_t > & E : used_global_textures ) {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Variable * v = material_storage - > global_shader_uniforms . variables . getptr ( E . key ) ;
2022-02-20 01:08:53 +01:00
if ( v ) {
v - > texture_materials . erase ( self ) ;
}
}
//unregister material from those using global textures
2022-04-03 18:56:43 +02:00
material_storage - > global_shader_uniforms . materials_using_texture . erase ( global_texture_E ) ;
2022-02-20 01:08:53 +01:00
}
if ( uniform_buffer ) {
glDeleteBuffers ( 1 , & uniform_buffer ) ;
2022-05-16 20:56:03 +02:00
uniform_buffer = 0 ;
2022-02-20 01:08:53 +01:00
}
}
2023-06-13 22:20:11 +02:00
void MaterialData : : update_textures ( const HashMap < StringName , Variant > & p_parameters , const HashMap < StringName , HashMap < int , RID > > & p_default_textures , const Vector < ShaderCompiler : : GeneratedCode : : Texture > & p_texture_uniforms , RID * p_textures , bool p_is_3d_shader_type ) {
2022-02-20 01:08:53 +01:00
TextureStorage * texture_storage = TextureStorage : : get_singleton ( ) ;
MaterialStorage * material_storage = MaterialStorage : : get_singleton ( ) ;
# ifdef TOOLS_ENABLED
Texture * roughness_detect_texture = nullptr ;
RS : : TextureDetectRoughnessChannel roughness_channel = RS : : TEXTURE_DETECT_ROUGHNESS_R ;
Texture * normal_detect_texture = nullptr ;
# endif
bool uses_global_textures = false ;
global_textures_pass + + ;
for ( int i = 0 , k = 0 ; i < p_texture_uniforms . size ( ) ; i + + ) {
const StringName & uniform_name = p_texture_uniforms [ i ] . name ;
int uniform_array_size = p_texture_uniforms [ i ] . array_size ;
Vector < RID > textures ;
2022-08-09 18:29:49 +02:00
if ( p_texture_uniforms [ i ] . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_SCREEN_TEXTURE | |
p_texture_uniforms [ i ] . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_NORMAL_ROUGHNESS_TEXTURE | |
p_texture_uniforms [ i ] . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_DEPTH_TEXTURE ) {
continue ;
}
2022-02-20 01:08:53 +01:00
if ( p_texture_uniforms [ i ] . global ) {
uses_global_textures = true ;
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Variable * v = material_storage - > global_shader_uniforms . variables . getptr ( uniform_name ) ;
2022-02-20 01:08:53 +01:00
if ( v ) {
if ( v - > buffer_index > = 0 ) {
2022-08-27 11:22:43 +02:00
WARN_PRINT ( " Shader uses global parameter texture ' " + String ( uniform_name ) + " ', but it changed type and is no longer a texture!. " ) ;
2022-02-20 01:08:53 +01:00
} else {
2022-05-13 15:04:37 +02:00
HashMap < StringName , uint64_t > : : Iterator E = used_global_textures . find ( uniform_name ) ;
2022-02-20 01:08:53 +01:00
if ( ! E ) {
E = used_global_textures . insert ( uniform_name , global_textures_pass ) ;
v - > texture_materials . insert ( self ) ;
} else {
2022-05-13 15:04:37 +02:00
E - > value = global_textures_pass ;
2022-02-20 01:08:53 +01:00
}
textures . push_back ( v - > override . get_type ( ) ! = Variant : : NIL ? v - > override : v - > value ) ;
}
} else {
2022-08-27 11:22:43 +02:00
WARN_PRINT ( " Shader uses global parameter texture ' " + String ( uniform_name ) + " ', but it was removed at some point. Material will not display correctly. " ) ;
2022-02-20 01:08:53 +01:00
}
} else {
2022-05-13 15:04:37 +02:00
HashMap < StringName , Variant > : : ConstIterator V = p_parameters . find ( uniform_name ) ;
2022-02-20 01:08:53 +01:00
if ( V ) {
2022-05-13 15:04:37 +02:00
if ( V - > value . is_array ( ) ) {
Array array = ( Array ) V - > value ;
2022-02-20 01:08:53 +01:00
if ( uniform_array_size > 0 ) {
2024-07-22 18:17:03 +02:00
int size = MIN ( uniform_array_size , array . size ( ) ) ;
for ( int j = 0 ; j < size ; j + + ) {
2022-02-20 01:08:53 +01:00
textures . push_back ( array [ j ] ) ;
}
} else {
if ( array . size ( ) > 0 ) {
textures . push_back ( array [ 0 ] ) ;
}
}
} else {
2022-05-13 15:04:37 +02:00
textures . push_back ( V - > value ) ;
2022-02-20 01:08:53 +01:00
}
}
if ( uniform_array_size > 0 ) {
if ( textures . size ( ) < uniform_array_size ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , HashMap < int , RID > > : : ConstIterator W = p_default_textures . find ( uniform_name ) ;
2022-02-20 01:08:53 +01:00
for ( int j = textures . size ( ) ; j < uniform_array_size ; j + + ) {
2022-05-13 15:04:37 +02:00
if ( W & & W - > value . has ( j ) ) {
textures . push_back ( W - > value [ j ] ) ;
2022-02-20 01:08:53 +01:00
} else {
textures . push_back ( RID ( ) ) ;
}
}
}
} else if ( textures . is_empty ( ) ) {
2022-05-13 15:04:37 +02:00
HashMap < StringName , HashMap < int , RID > > : : ConstIterator W = p_default_textures . find ( uniform_name ) ;
if ( W & & W - > value . has ( 0 ) ) {
textures . push_back ( W - > value [ 0 ] ) ;
2022-02-20 01:08:53 +01:00
}
}
}
RID gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_WHITE ) ;
if ( textures . is_empty ( ) ) {
//check default usage
switch ( p_texture_uniforms [ i ] . type ) {
case ShaderLanguage : : TYPE_ISAMPLER2D :
case ShaderLanguage : : TYPE_USAMPLER2D :
case ShaderLanguage : : TYPE_SAMPLER2D : {
switch ( p_texture_uniforms [ i ] . hint ) {
2022-05-05 20:23:40 +02:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_DEFAULT_BLACK : {
2022-02-20 01:08:53 +01:00
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_BLACK ) ;
} break ;
2021-08-14 18:29:52 +02:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_DEFAULT_TRANSPARENT : {
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_TRANSPARENT ) ;
} break ;
2022-02-20 01:08:53 +01:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_ANISOTROPY : {
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_ANISO ) ;
} break ;
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_NORMAL : {
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_NORMAL ) ;
} break ;
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_ROUGHNESS_NORMAL : {
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_NORMAL ) ;
} break ;
default : {
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_WHITE ) ;
} break ;
}
} break ;
case ShaderLanguage : : TYPE_SAMPLERCUBE : {
switch ( p_texture_uniforms [ i ] . hint ) {
2022-05-05 20:23:40 +02:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_DEFAULT_BLACK : {
2022-02-20 01:08:53 +01:00
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_CUBEMAP_BLACK ) ;
} break ;
default : {
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_CUBEMAP_WHITE ) ;
} break ;
}
} break ;
case ShaderLanguage : : TYPE_SAMPLERCUBEARRAY : {
2023-06-20 23:03:14 +02:00
ERR_PRINT_ONCE ( " Type: SamplerCubeArray not supported in GL Compatibility rendering backend, please use another type. " ) ;
2022-02-20 01:08:53 +01:00
} break ;
case ShaderLanguage : : TYPE_ISAMPLER3D :
case ShaderLanguage : : TYPE_USAMPLER3D :
case ShaderLanguage : : TYPE_SAMPLER3D : {
switch ( p_texture_uniforms [ i ] . hint ) {
2022-05-05 20:23:40 +02:00
case ShaderLanguage : : ShaderNode : : Uniform : : HINT_DEFAULT_BLACK : {
2022-02-20 01:08:53 +01:00
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_3D_BLACK ) ;
} break ;
default : {
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_3D_WHITE ) ;
} break ;
}
} break ;
case ShaderLanguage : : TYPE_ISAMPLER2DARRAY :
case ShaderLanguage : : TYPE_USAMPLER2DARRAY :
case ShaderLanguage : : TYPE_SAMPLER2DARRAY : {
gl_texture = texture_storage - > texture_gl_get_default ( DEFAULT_GL_TEXTURE_2D_ARRAY_WHITE ) ;
} break ;
default : {
}
}
# ifdef TOOLS_ENABLED
if ( roughness_detect_texture & & normal_detect_texture & & ! normal_detect_texture - > path . is_empty ( ) ) {
roughness_detect_texture - > detect_roughness_callback ( roughness_detect_texture - > detect_roughness_callback_ud , normal_detect_texture - > path , roughness_channel ) ;
}
# endif
if ( uniform_array_size > 0 ) {
for ( int j = 0 ; j < uniform_array_size ; j + + ) {
p_textures [ k + + ] = gl_texture ;
}
} else {
p_textures [ k + + ] = gl_texture ;
}
} else {
for ( int j = 0 ; j < textures . size ( ) ; j + + ) {
Texture * tex = TextureStorage : : get_singleton ( ) - > get_texture ( textures [ j ] ) ;
if ( tex ) {
gl_texture = textures [ j ] ;
# ifdef TOOLS_ENABLED
2023-06-13 22:20:11 +02:00
if ( tex - > detect_3d_callback & & p_is_3d_shader_type ) {
2022-02-20 01:08:53 +01:00
tex - > detect_3d_callback ( tex - > detect_3d_callback_ud ) ;
}
if ( tex - > detect_normal_callback & & ( p_texture_uniforms [ i ] . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_NORMAL | | p_texture_uniforms [ i ] . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_ROUGHNESS_NORMAL ) ) {
if ( p_texture_uniforms [ i ] . hint = = ShaderLanguage : : ShaderNode : : Uniform : : HINT_ROUGHNESS_NORMAL ) {
normal_detect_texture = tex ;
}
tex - > detect_normal_callback ( tex - > detect_normal_callback_ud ) ;
}
if ( tex - > detect_roughness_callback & & ( p_texture_uniforms [ i ] . hint > = ShaderLanguage : : ShaderNode : : Uniform : : HINT_ROUGHNESS_R | | p_texture_uniforms [ i ] . hint < = ShaderLanguage : : ShaderNode : : Uniform : : HINT_ROUGHNESS_GRAY ) ) {
//find the normal texture
roughness_detect_texture = tex ;
roughness_channel = RS : : TextureDetectRoughnessChannel ( p_texture_uniforms [ i ] . hint - ShaderLanguage : : ShaderNode : : Uniform : : HINT_ROUGHNESS_R ) ;
}
# endif
}
# ifdef TOOLS_ENABLED
if ( roughness_detect_texture & & normal_detect_texture & & ! normal_detect_texture - > path . is_empty ( ) ) {
roughness_detect_texture - > detect_roughness_callback ( roughness_detect_texture - > detect_roughness_callback_ud , normal_detect_texture - > path , roughness_channel ) ;
}
# endif
p_textures [ k + + ] = gl_texture ;
}
}
}
{
//for textures no longer used, unregister them
2022-05-13 15:04:37 +02:00
List < StringName > to_delete ;
for ( KeyValue < StringName , uint64_t > & E : used_global_textures ) {
if ( E . value ! = global_textures_pass ) {
to_delete . push_back ( E . key ) ;
2022-02-20 01:08:53 +01:00
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Variable * v = material_storage - > global_shader_uniforms . variables . getptr ( E . key ) ;
2022-02-20 01:08:53 +01:00
if ( v ) {
v - > texture_materials . erase ( self ) ;
}
}
}
while ( to_delete . front ( ) ) {
used_global_textures . erase ( to_delete . front ( ) - > get ( ) ) ;
to_delete . pop_front ( ) ;
}
//handle registering/unregistering global textures
if ( uses_global_textures ! = ( global_texture_E ! = nullptr ) ) {
if ( uses_global_textures ) {
2022-04-03 18:56:43 +02:00
global_texture_E = material_storage - > global_shader_uniforms . materials_using_texture . push_back ( self ) ;
2022-02-20 01:08:53 +01:00
} else {
2022-04-03 18:56:43 +02:00
material_storage - > global_shader_uniforms . materials_using_texture . erase ( global_texture_E ) ;
2022-02-20 01:08:53 +01:00
global_texture_E = nullptr ;
}
}
}
}
2023-06-13 22:20:11 +02:00
void MaterialData : : update_parameters_internal ( const HashMap < StringName , Variant > & p_parameters , bool p_uniform_dirty , bool p_textures_dirty , const HashMap < StringName , ShaderLanguage : : ShaderNode : : Uniform > & p_uniforms , const uint32_t * p_uniform_offsets , const Vector < ShaderCompiler : : GeneratedCode : : Texture > & p_texture_uniforms , const HashMap < StringName , HashMap < int , RID > > & p_default_texture_params , uint32_t p_ubo_size , bool p_is_3d_shader_type ) {
2022-02-20 01:08:53 +01:00
if ( ( uint32_t ) ubo_data . size ( ) ! = p_ubo_size ) {
p_uniform_dirty = true ;
if ( ! uniform_buffer ) {
glGenBuffers ( 1 , & uniform_buffer ) ;
}
ubo_data . resize ( p_ubo_size ) ;
if ( ubo_data . size ( ) ) {
2024-05-30 21:30:53 +02:00
ERR_FAIL_COND ( p_ubo_size > uint32_t ( Config : : get_singleton ( ) - > max_uniform_buffer_size ) ) ;
2022-02-20 01:08:53 +01:00
memset ( ubo_data . ptrw ( ) , 0 , ubo_data . size ( ) ) ; //clear
}
}
//check whether buffer changed
if ( p_uniform_dirty & & ubo_data . size ( ) ) {
2023-06-13 22:20:11 +02:00
update_uniform_buffer ( p_uniforms , p_uniform_offsets , p_parameters , ubo_data . ptrw ( ) , ubo_data . size ( ) ) ;
2022-02-20 01:08:53 +01:00
glBindBuffer ( GL_UNIFORM_BUFFER , uniform_buffer ) ;
glBufferData ( GL_UNIFORM_BUFFER , ubo_data . size ( ) , ubo_data . ptrw ( ) , GL_DYNAMIC_DRAW ) ;
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
}
uint32_t tex_uniform_count = 0U ;
for ( int i = 0 ; i < p_texture_uniforms . size ( ) ; i + + ) {
tex_uniform_count + = uint32_t ( p_texture_uniforms [ i ] . array_size > 0 ? p_texture_uniforms [ i ] . array_size : 1 ) ;
}
if ( ( uint32_t ) texture_cache . size ( ) ! = tex_uniform_count | | p_textures_dirty ) {
texture_cache . resize ( tex_uniform_count ) ;
p_textures_dirty = true ;
}
if ( p_textures_dirty & & tex_uniform_count ) {
2023-06-13 22:20:11 +02:00
update_textures ( p_parameters , p_default_texture_params , p_texture_uniforms , texture_cache . ptrw ( ) , p_is_3d_shader_type ) ;
2022-02-20 01:08:53 +01:00
}
}
///////////////////////////////////////////////////////////////////////////
// Material Storage
2022-03-21 12:25:25 +01:00
MaterialStorage * MaterialStorage : : singleton = nullptr ;
MaterialStorage * MaterialStorage : : get_singleton ( ) {
return singleton ;
}
MaterialStorage : : MaterialStorage ( ) {
singleton = this ;
2022-05-03 22:28:15 +02:00
shader_data_request_func [ RS : : SHADER_SPATIAL ] = _create_scene_shader_func ;
2022-02-20 01:08:53 +01:00
shader_data_request_func [ RS : : SHADER_CANVAS_ITEM ] = _create_canvas_shader_func ;
2022-11-08 07:40:03 +01:00
shader_data_request_func [ RS : : SHADER_PARTICLES ] = _create_particles_shader_func ;
2022-04-30 00:34:01 +02:00
shader_data_request_func [ RS : : SHADER_SKY ] = _create_sky_shader_func ;
2022-02-20 01:08:53 +01:00
shader_data_request_func [ RS : : SHADER_FOG ] = nullptr ;
2022-05-03 22:28:15 +02:00
material_data_request_func [ RS : : SHADER_SPATIAL ] = _create_scene_material_func ;
2022-02-20 01:08:53 +01:00
material_data_request_func [ RS : : SHADER_CANVAS_ITEM ] = _create_canvas_material_func ;
2022-11-08 07:40:03 +01:00
material_data_request_func [ RS : : SHADER_PARTICLES ] = _create_particles_material_func ;
2022-04-30 00:34:01 +02:00
material_data_request_func [ RS : : SHADER_SKY ] = _create_sky_material_func ;
2022-02-20 01:08:53 +01:00
material_data_request_func [ RS : : SHADER_FOG ] = nullptr ;
2022-04-03 18:56:43 +02:00
static_assert ( sizeof ( GlobalShaderUniforms : : Value ) = = 16 ) ;
2022-02-20 01:08:53 +01:00
2024-05-30 21:30:53 +02:00
global_shader_uniforms . buffer_size = MAX ( 16 , ( int ) GLOBAL_GET ( " rendering/limits/global_shader_variables/buffer_size " ) ) ;
if ( global_shader_uniforms . buffer_size * sizeof ( GlobalShaderUniforms : : Value ) > uint32_t ( Config : : get_singleton ( ) - > max_uniform_buffer_size ) ) {
2024-06-27 01:57:24 +02:00
// Limit to maximum support UBO size.
2024-05-30 21:30:53 +02:00
global_shader_uniforms . buffer_size = uint32_t ( Config : : get_singleton ( ) - > max_uniform_buffer_size ) / sizeof ( GlobalShaderUniforms : : Value ) ;
2022-02-20 01:08:53 +01:00
}
2022-04-03 18:56:43 +02:00
global_shader_uniforms . buffer_values = memnew_arr ( GlobalShaderUniforms : : Value , global_shader_uniforms . buffer_size ) ;
memset ( global_shader_uniforms . buffer_values , 0 , sizeof ( GlobalShaderUniforms : : Value ) * global_shader_uniforms . buffer_size ) ;
global_shader_uniforms . buffer_usage = memnew_arr ( GlobalShaderUniforms : : ValueUsage , global_shader_uniforms . buffer_size ) ;
2024-06-27 01:57:24 +02:00
global_shader_uniforms . buffer_dirty_regions = memnew_arr ( bool , 1 + ( global_shader_uniforms . buffer_size / GlobalShaderUniforms : : BUFFER_DIRTY_REGION_SIZE ) ) ;
memset ( global_shader_uniforms . buffer_dirty_regions , 0 , sizeof ( bool ) * ( 1 + ( global_shader_uniforms . buffer_size / GlobalShaderUniforms : : BUFFER_DIRTY_REGION_SIZE ) ) ) ;
2022-04-03 18:56:43 +02:00
glGenBuffers ( 1 , & global_shader_uniforms . buffer ) ;
glBindBuffer ( GL_UNIFORM_BUFFER , global_shader_uniforms . buffer ) ;
glBufferData ( GL_UNIFORM_BUFFER , sizeof ( GlobalShaderUniforms : : Value ) * global_shader_uniforms . buffer_size , nullptr , GL_DYNAMIC_DRAW ) ;
2022-02-20 01:08:53 +01:00
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
{
// Setup CanvasItem compiler
ShaderCompiler : : DefaultIdentifierActions actions ;
actions . renames [ " VERTEX " ] = " vertex " ;
actions . renames [ " LIGHT_VERTEX " ] = " light_vertex " ;
actions . renames [ " SHADOW_VERTEX " ] = " shadow_vertex " ;
actions . renames [ " UV " ] = " uv " ;
2023-02-26 08:39:43 +01:00
actions . renames [ " POINT_SIZE " ] = " point_size " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " MODEL_MATRIX " ] = " model_matrix " ;
2022-09-14 21:41:08 +02:00
actions . renames [ " CANVAS_MATRIX " ] = " canvas_transform " ;
actions . renames [ " SCREEN_MATRIX " ] = " screen_transform " ;
actions . renames [ " TIME " ] = " time " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " PI " ] = _MKSTR ( Math_PI ) ;
actions . renames [ " TAU " ] = _MKSTR ( Math_TAU ) ;
actions . renames [ " E " ] = _MKSTR ( Math_E ) ;
actions . renames [ " AT_LIGHT_PASS " ] = " false " ;
actions . renames [ " INSTANCE_CUSTOM " ] = " instance_custom " ;
actions . renames [ " COLOR " ] = " color " ;
actions . renames [ " NORMAL " ] = " normal " ;
actions . renames [ " NORMAL_MAP " ] = " normal_map " ;
actions . renames [ " NORMAL_MAP_DEPTH " ] = " normal_map_depth " ;
actions . renames [ " TEXTURE " ] = " color_texture " ;
2022-10-04 03:37:57 +02:00
actions . renames [ " TEXTURE_PIXEL_SIZE " ] = " color_texture_pixel_size " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " NORMAL_TEXTURE " ] = " normal_texture " ;
actions . renames [ " SPECULAR_SHININESS_TEXTURE " ] = " specular_texture " ;
actions . renames [ " SPECULAR_SHININESS " ] = " specular_shininess " ;
actions . renames [ " SCREEN_UV " ] = " screen_uv " ;
2022-09-14 21:41:08 +02:00
actions . renames [ " SCREEN_PIXEL_SIZE " ] = " screen_pixel_size " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " FRAGCOORD " ] = " gl_FragCoord " ;
actions . renames [ " POINT_COORD " ] = " gl_PointCoord " ;
2023-11-07 17:55:51 +01:00
actions . renames [ " INSTANCE_ID " ] = " gl_InstanceID " ;
actions . renames [ " VERTEX_ID " ] = " gl_VertexID " ;
2022-02-20 01:08:53 +01:00
2023-12-27 21:58:50 +01:00
actions . renames [ " CUSTOM0 " ] = " custom0 " ;
actions . renames [ " CUSTOM1 " ] = " custom1 " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " LIGHT_POSITION " ] = " light_position " ;
2022-09-28 20:45:08 +02:00
actions . renames [ " LIGHT_DIRECTION " ] = " light_direction " ;
actions . renames [ " LIGHT_IS_DIRECTIONAL " ] = " is_directional " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " LIGHT_COLOR " ] = " light_color " ;
actions . renames [ " LIGHT_ENERGY " ] = " light_energy " ;
actions . renames [ " LIGHT " ] = " light " ;
actions . renames [ " SHADOW_MODULATE " ] = " shadow_modulate " ;
actions . renames [ " texture_sdf " ] = " texture_sdf " ;
actions . renames [ " texture_sdf_normal " ] = " texture_sdf_normal " ;
actions . renames [ " sdf_to_screen_uv " ] = " sdf_to_screen_uv " ;
actions . renames [ " screen_uv_to_sdf " ] = " screen_uv_to_sdf " ;
actions . usage_defines [ " COLOR " ] = " #define COLOR_USED \n " ;
actions . usage_defines [ " SCREEN_UV " ] = " #define SCREEN_UV_USED \n " ;
actions . usage_defines [ " SCREEN_PIXEL_SIZE " ] = " @SCREEN_UV " ;
actions . usage_defines [ " NORMAL " ] = " #define NORMAL_USED \n " ;
actions . usage_defines [ " NORMAL_MAP " ] = " #define NORMAL_MAP_USED \n " ;
2022-06-21 06:28:50 +02:00
actions . usage_defines [ " SPECULAR_SHININESS " ] = " #define SPECULAR_SHININESS_USED \n " ;
2023-12-27 21:58:50 +01:00
actions . usage_defines [ " CUSTOM0 " ] = " #define CUSTOM0_USED \n " ;
actions . usage_defines [ " CUSTOM1 " ] = " #define CUSTOM1_USED \n " ;
2022-02-20 01:08:53 +01:00
actions . render_mode_defines [ " skip_vertex_transform " ] = " #define SKIP_TRANSFORM_USED \n " ;
actions . render_mode_defines [ " unshaded " ] = " #define MODE_UNSHADED \n " ;
actions . render_mode_defines [ " light_only " ] = " #define MODE_LIGHT_ONLY \n " ;
2023-08-30 14:59:06 +02:00
actions . render_mode_defines [ " world_vertex_coords " ] = " #define USE_WORLD_VERTEX_COORDS \n " ;
2022-02-20 01:08:53 +01:00
2023-01-26 21:14:45 +01:00
actions . global_buffer_array_variable = " global_shader_uniforms " ;
2022-02-20 01:08:53 +01:00
shaders . compiler_canvas . initialize ( actions ) ;
}
{
// Setup Scene compiler
2022-05-03 22:28:15 +02:00
2022-02-20 01:08:53 +01:00
//shader compiler
ShaderCompiler : : DefaultIdentifierActions actions ;
actions . renames [ " MODEL_MATRIX " ] = " model_matrix " ;
actions . renames [ " MODEL_NORMAL_MATRIX " ] = " model_normal_matrix " ;
actions . renames [ " VIEW_MATRIX " ] = " scene_data.view_matrix " ;
actions . renames [ " INV_VIEW_MATRIX " ] = " scene_data.inv_view_matrix " ;
actions . renames [ " PROJECTION_MATRIX " ] = " projection_matrix " ;
actions . renames [ " INV_PROJECTION_MATRIX " ] = " inv_projection_matrix " ;
actions . renames [ " MODELVIEW_MATRIX " ] = " modelview " ;
actions . renames [ " MODELVIEW_NORMAL_MATRIX " ] = " modelview_normal " ;
2023-02-01 04:53:54 +01:00
actions . renames [ " MAIN_CAM_INV_VIEW_MATRIX " ] = " scene_data.main_cam_inv_view_matrix " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " VERTEX " ] = " vertex " ;
actions . renames [ " NORMAL " ] = " normal " ;
actions . renames [ " TANGENT " ] = " tangent " ;
actions . renames [ " BINORMAL " ] = " binormal " ;
actions . renames [ " POSITION " ] = " position " ;
actions . renames [ " UV " ] = " uv_interp " ;
actions . renames [ " UV2 " ] = " uv2_interp " ;
actions . renames [ " COLOR " ] = " color_interp " ;
2023-02-26 08:39:43 +01:00
actions . renames [ " POINT_SIZE " ] = " point_size " ;
2022-06-24 20:22:26 +02:00
actions . renames [ " INSTANCE_ID " ] = " gl_InstanceID " ;
actions . renames [ " VERTEX_ID " ] = " gl_VertexID " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " ALPHA_SCISSOR_THRESHOLD " ] = " alpha_scissor_threshold " ;
actions . renames [ " ALPHA_HASH_SCALE " ] = " alpha_hash_scale " ;
actions . renames [ " ALPHA_ANTIALIASING_EDGE " ] = " alpha_antialiasing_edge " ;
actions . renames [ " ALPHA_TEXTURE_COORDINATE " ] = " alpha_texture_coordinate " ;
//builtins
actions . renames [ " TIME " ] = " scene_data.time " ;
2023-01-13 23:02:46 +01:00
actions . renames [ " EXPOSURE " ] = " (1.0 / scene_data.emissive_exposure_normalization) " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " PI " ] = _MKSTR ( Math_PI ) ;
actions . renames [ " TAU " ] = _MKSTR ( Math_TAU ) ;
actions . renames [ " E " ] = _MKSTR ( Math_E ) ;
actions . renames [ " VIEWPORT_SIZE " ] = " scene_data.viewport_size " ;
actions . renames [ " FRAGCOORD " ] = " gl_FragCoord " ;
actions . renames [ " FRONT_FACING " ] = " gl_FrontFacing " ;
actions . renames [ " NORMAL_MAP " ] = " normal_map " ;
actions . renames [ " NORMAL_MAP_DEPTH " ] = " normal_map_depth " ;
actions . renames [ " ALBEDO " ] = " albedo " ;
actions . renames [ " ALPHA " ] = " alpha " ;
2024-05-01 11:12:31 +02:00
actions . renames [ " PREMUL_ALPHA_FACTOR " ] = " premul_alpha " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " METALLIC " ] = " metallic " ;
actions . renames [ " SPECULAR " ] = " specular " ;
actions . renames [ " ROUGHNESS " ] = " roughness " ;
actions . renames [ " RIM " ] = " rim " ;
actions . renames [ " RIM_TINT " ] = " rim_tint " ;
actions . renames [ " CLEARCOAT " ] = " clearcoat " ;
actions . renames [ " CLEARCOAT_ROUGHNESS " ] = " clearcoat_roughness " ;
actions . renames [ " ANISOTROPY " ] = " anisotropy " ;
actions . renames [ " ANISOTROPY_FLOW " ] = " anisotropy_flow " ;
actions . renames [ " SSS_STRENGTH " ] = " sss_strength " ;
actions . renames [ " SSS_TRANSMITTANCE_COLOR " ] = " transmittance_color " ;
actions . renames [ " SSS_TRANSMITTANCE_DEPTH " ] = " transmittance_depth " ;
actions . renames [ " SSS_TRANSMITTANCE_BOOST " ] = " transmittance_boost " ;
actions . renames [ " BACKLIGHT " ] = " backlight " ;
actions . renames [ " AO " ] = " ao " ;
actions . renames [ " AO_LIGHT_AFFECT " ] = " ao_light_affect " ;
actions . renames [ " EMISSION " ] = " emission " ;
actions . renames [ " POINT_COORD " ] = " gl_PointCoord " ;
actions . renames [ " INSTANCE_CUSTOM " ] = " instance_custom " ;
actions . renames [ " SCREEN_UV " ] = " screen_uv " ;
actions . renames [ " DEPTH " ] = " gl_FragDepth " ;
2022-07-26 07:07:22 +02:00
actions . renames [ " FOG " ] = " fog " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " RADIANCE " ] = " custom_radiance " ;
actions . renames [ " IRRADIANCE " ] = " custom_irradiance " ;
actions . renames [ " BONE_INDICES " ] = " bone_attrib " ;
actions . renames [ " BONE_WEIGHTS " ] = " weight_attrib " ;
actions . renames [ " CUSTOM0 " ] = " custom0_attrib " ;
actions . renames [ " CUSTOM1 " ] = " custom1_attrib " ;
actions . renames [ " CUSTOM2 " ] = " custom2_attrib " ;
actions . renames [ " CUSTOM3 " ] = " custom3_attrib " ;
actions . renames [ " OUTPUT_IS_SRGB " ] = " SHADER_IS_SRGB " ;
2024-08-02 12:25:19 +02:00
actions . renames [ " CLIP_SPACE_FAR " ] = " SHADER_SPACE_FAR " ;
2024-04-25 06:41:18 +02:00
actions . renames [ " LIGHT_VERTEX " ] = " light_vertex " ;
2022-02-20 01:08:53 +01:00
2022-07-28 23:56:28 +02:00
actions . renames [ " NODE_POSITION_WORLD " ] = " model_matrix[3].xyz " ;
actions . renames [ " CAMERA_POSITION_WORLD " ] = " scene_data.inv_view_matrix[3].xyz " ;
2023-12-26 07:09:44 +01:00
actions . renames [ " CAMERA_DIRECTION_WORLD " ] = " scene_data.inv_view_matrix[2].xyz " ;
2022-10-13 04:33:06 +02:00
actions . renames [ " CAMERA_VISIBLE_LAYERS " ] = " scene_data.camera_visible_layers " ;
2023-04-15 19:52:09 +02:00
actions . renames [ " NODE_POSITION_VIEW " ] = " (scene_data.view_matrix * model_matrix)[3].xyz " ;
2022-07-28 23:56:28 +02:00
2022-02-20 01:08:53 +01:00
actions . renames [ " VIEW_INDEX " ] = " ViewIndex " ;
2023-01-15 06:07:59 +01:00
actions . renames [ " VIEW_MONO_LEFT " ] = " uint(0) " ;
actions . renames [ " VIEW_RIGHT " ] = " uint(1) " ;
2023-02-01 02:33:22 +01:00
actions . renames [ " EYE_OFFSET " ] = " eye_offset " ;
2022-02-20 01:08:53 +01:00
//for light
actions . renames [ " VIEW " ] = " view " ;
2023-03-18 10:03:07 +01:00
actions . renames [ " SPECULAR_AMOUNT " ] = " specular_amount " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " LIGHT_COLOR " ] = " light_color " ;
2023-04-20 14:33:30 +02:00
actions . renames [ " LIGHT_IS_DIRECTIONAL " ] = " is_directional " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " LIGHT " ] = " light " ;
actions . renames [ " ATTENUATION " ] = " attenuation " ;
actions . renames [ " DIFFUSE_LIGHT " ] = " diffuse_light " ;
actions . renames [ " SPECULAR_LIGHT " ] = " specular_light " ;
actions . usage_defines [ " NORMAL " ] = " #define NORMAL_USED \n " ;
actions . usage_defines [ " TANGENT " ] = " #define TANGENT_USED \n " ;
actions . usage_defines [ " BINORMAL " ] = " @TANGENT " ;
actions . usage_defines [ " RIM " ] = " #define LIGHT_RIM_USED \n " ;
actions . usage_defines [ " RIM_TINT " ] = " @RIM " ;
actions . usage_defines [ " CLEARCOAT " ] = " #define LIGHT_CLEARCOAT_USED \n " ;
actions . usage_defines [ " CLEARCOAT_ROUGHNESS " ] = " @CLEARCOAT " ;
actions . usage_defines [ " ANISOTROPY " ] = " #define LIGHT_ANISOTROPY_USED \n " ;
actions . usage_defines [ " ANISOTROPY_FLOW " ] = " @ANISOTROPY " ;
actions . usage_defines [ " AO " ] = " #define AO_USED \n " ;
actions . usage_defines [ " AO_LIGHT_AFFECT " ] = " #define AO_USED \n " ;
actions . usage_defines [ " UV " ] = " #define UV_USED \n " ;
actions . usage_defines [ " UV2 " ] = " #define UV2_USED \n " ;
actions . usage_defines [ " BONE_INDICES " ] = " #define BONES_USED \n " ;
actions . usage_defines [ " BONE_WEIGHTS " ] = " #define WEIGHTS_USED \n " ;
actions . usage_defines [ " CUSTOM0 " ] = " #define CUSTOM0_USED \n " ;
actions . usage_defines [ " CUSTOM1 " ] = " #define CUSTOM1_USED \n " ;
actions . usage_defines [ " CUSTOM2 " ] = " #define CUSTOM2_USED \n " ;
actions . usage_defines [ " CUSTOM3 " ] = " #define CUSTOM3_USED \n " ;
actions . usage_defines [ " NORMAL_MAP " ] = " #define NORMAL_MAP_USED \n " ;
actions . usage_defines [ " NORMAL_MAP_DEPTH " ] = " @NORMAL_MAP " ;
actions . usage_defines [ " COLOR " ] = " #define COLOR_USED \n " ;
actions . usage_defines [ " INSTANCE_CUSTOM " ] = " #define ENABLE_INSTANCE_CUSTOM \n " ;
actions . usage_defines [ " POSITION " ] = " #define OVERRIDE_POSITION \n " ;
2024-04-25 06:41:18 +02:00
actions . usage_defines [ " LIGHT_VERTEX " ] = " #define LIGHT_VERTEX_USED \n " ;
2022-02-20 01:08:53 +01:00
actions . usage_defines [ " ALPHA_SCISSOR_THRESHOLD " ] = " #define ALPHA_SCISSOR_USED \n " ;
actions . usage_defines [ " ALPHA_HASH_SCALE " ] = " #define ALPHA_HASH_USED \n " ;
actions . usage_defines [ " ALPHA_ANTIALIASING_EDGE " ] = " #define ALPHA_ANTIALIASING_EDGE_USED \n " ;
actions . usage_defines [ " ALPHA_TEXTURE_COORDINATE " ] = " @ALPHA_ANTIALIASING_EDGE " ;
2023-12-01 15:57:29 +01:00
actions . usage_defines [ " PREMULT_ALPHA_FACTOR " ] = " #define PREMULT_ALPHA_USED " ;
2022-02-20 01:08:53 +01:00
actions . usage_defines [ " SSS_STRENGTH " ] = " #define ENABLE_SSS \n " ;
actions . usage_defines [ " SSS_TRANSMITTANCE_DEPTH " ] = " #define ENABLE_TRANSMITTANCE \n " ;
actions . usage_defines [ " BACKLIGHT " ] = " #define LIGHT_BACKLIGHT_USED \n " ;
actions . usage_defines [ " SCREEN_UV " ] = " #define SCREEN_UV_USED \n " ;
actions . usage_defines [ " FOG " ] = " #define CUSTOM_FOG_USED \n " ;
actions . usage_defines [ " RADIANCE " ] = " #define CUSTOM_RADIANCE_USED \n " ;
actions . usage_defines [ " IRRADIANCE " ] = " #define CUSTOM_IRRADIANCE_USED \n " ;
actions . render_mode_defines [ " skip_vertex_transform " ] = " #define SKIP_TRANSFORM_USED \n " ;
actions . render_mode_defines [ " world_vertex_coords " ] = " #define VERTEX_WORLD_COORDS_USED \n " ;
actions . render_mode_defines [ " ensure_correct_normals " ] = " #define ENSURE_CORRECT_NORMALS \n " ;
actions . render_mode_defines [ " cull_front " ] = " #define DO_SIDE_CHECK \n " ;
actions . render_mode_defines [ " cull_disabled " ] = " #define DO_SIDE_CHECK \n " ;
actions . render_mode_defines [ " particle_trails " ] = " #define USE_PARTICLE_TRAILS \n " ;
2023-07-24 23:21:04 +02:00
actions . render_mode_defines [ " depth_prepass_alpha " ] = " #define USE_OPAQUE_PREPASS \n " ;
2022-02-20 01:08:53 +01:00
bool force_lambert = GLOBAL_GET ( " rendering/shading/overrides/force_lambert_over_burley " ) ;
if ( ! force_lambert ) {
actions . render_mode_defines [ " diffuse_burley " ] = " #define DIFFUSE_BURLEY \n " ;
}
actions . render_mode_defines [ " diffuse_lambert_wrap " ] = " #define DIFFUSE_LAMBERT_WRAP \n " ;
actions . render_mode_defines [ " diffuse_toon " ] = " #define DIFFUSE_TOON \n " ;
actions . render_mode_defines [ " sss_mode_skin " ] = " #define SSS_MODE_SKIN \n " ;
actions . render_mode_defines [ " specular_schlick_ggx " ] = " #define SPECULAR_SCHLICK_GGX \n " ;
actions . render_mode_defines [ " specular_toon " ] = " #define SPECULAR_TOON \n " ;
actions . render_mode_defines [ " specular_disabled " ] = " #define SPECULAR_DISABLED \n " ;
actions . render_mode_defines [ " shadows_disabled " ] = " #define SHADOWS_DISABLED \n " ;
actions . render_mode_defines [ " ambient_light_disabled " ] = " #define AMBIENT_LIGHT_DISABLED \n " ;
actions . render_mode_defines [ " shadow_to_opacity " ] = " #define USE_SHADOW_TO_OPACITY \n " ;
actions . render_mode_defines [ " unshaded " ] = " #define MODE_UNSHADED \n " ;
2023-09-04 00:04:14 +02:00
actions . render_mode_defines [ " fog_disabled " ] = " #define FOG_DISABLED \n " ;
2022-02-20 01:08:53 +01:00
actions . default_filter = ShaderLanguage : : FILTER_LINEAR_MIPMAP ;
actions . default_repeat = ShaderLanguage : : REPEAT_ENABLE ;
2023-01-29 10:14:22 +01:00
actions . check_multiview_samplers = RasterizerGLES3 : : get_singleton ( ) - > is_xr_enabled ( ) ;
2023-01-26 21:14:45 +01:00
actions . global_buffer_array_variable = " global_shader_uniforms " ;
2023-01-15 06:07:59 +01:00
2022-05-03 22:28:15 +02:00
shaders . compiler_scene . initialize ( actions ) ;
2022-02-20 01:08:53 +01:00
}
{
// Setup Particles compiler
2022-11-08 07:40:03 +01:00
ShaderCompiler : : DefaultIdentifierActions actions ;
actions . renames [ " COLOR " ] = " out_color " ;
actions . renames [ " VELOCITY " ] = " out_velocity_flags.xyz " ;
2022-02-20 01:08:53 +01:00
//actions.renames["MASS"] = "mass"; ?
actions . renames [ " ACTIVE " ] = " particle_active " ;
actions . renames [ " RESTART " ] = " restart " ;
2022-11-08 07:40:03 +01:00
actions . renames [ " CUSTOM " ] = " out_custom " ;
for ( int i = 0 ; i < PARTICLES_MAX_USERDATAS ; i + + ) {
2022-02-20 01:08:53 +01:00
String udname = " USERDATA " + itos ( i + 1 ) ;
2022-11-08 07:40:03 +01:00
actions . renames [ udname ] = " out_userdata " + itos ( i + 1 ) ;
2022-02-20 01:08:53 +01:00
actions . usage_defines [ udname ] = " #define USERDATA " + itos ( i + 1 ) + " _USED \n " ;
}
2022-11-08 07:40:03 +01:00
actions . renames [ " TRANSFORM " ] = " xform " ;
actions . renames [ " TIME " ] = " time " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " PI " ] = _MKSTR ( Math_PI ) ;
actions . renames [ " TAU " ] = _MKSTR ( Math_TAU ) ;
actions . renames [ " E " ] = _MKSTR ( Math_E ) ;
2022-11-08 07:40:03 +01:00
actions . renames [ " LIFETIME " ] = " lifetime " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " DELTA " ] = " local_delta " ;
actions . renames [ " NUMBER " ] = " particle_number " ;
actions . renames [ " INDEX " ] = " index " ;
2023-08-13 13:08:52 +02:00
actions . renames [ " AMOUNT_RATIO " ] = " amount_ratio " ;
2022-02-20 01:08:53 +01:00
//actions.renames["GRAVITY"] = "current_gravity";
2022-11-08 07:40:03 +01:00
actions . renames [ " EMISSION_TRANSFORM " ] = " emission_transform " ;
actions . renames [ " RANDOM_SEED " ] = " random_seed " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " RESTART_POSITION " ] = " restart_position " ;
actions . renames [ " RESTART_ROT_SCALE " ] = " restart_rotation_scale " ;
actions . renames [ " RESTART_VELOCITY " ] = " restart_velocity " ;
actions . renames [ " RESTART_COLOR " ] = " restart_color " ;
actions . renames [ " RESTART_CUSTOM " ] = " restart_custom " ;
actions . renames [ " COLLIDED " ] = " collided " ;
actions . renames [ " COLLISION_NORMAL " ] = " collision_normal " ;
actions . renames [ " COLLISION_DEPTH " ] = " collision_depth " ;
actions . renames [ " ATTRACTOR_FORCE " ] = " attractor_force " ;
2023-08-13 13:08:52 +02:00
actions . renames [ " EMITTER_VELOCITY " ] = " emitter_velocity " ;
actions . renames [ " INTERPOLATE_TO_END " ] = " interp_to_end " ;
2022-02-20 01:08:53 +01:00
2023-06-20 23:03:14 +02:00
// These are unsupported, but may be used by users. To avoid compile time overhead, we add the stub only when used.
actions . renames [ " FLAG_EMIT_POSITION " ] = " uint(1) " ;
actions . renames [ " FLAG_EMIT_ROT_SCALE " ] = " uint(2) " ;
actions . renames [ " FLAG_EMIT_VELOCITY " ] = " uint(4) " ;
actions . renames [ " FLAG_EMIT_COLOR " ] = " uint(8) " ;
actions . renames [ " FLAG_EMIT_CUSTOM " ] = " uint(16) " ;
actions . renames [ " emit_subparticle " ] = " emit_subparticle " ;
actions . usage_defines [ " emit_subparticle " ] = " \n bool emit_subparticle(mat4 p_xform, vec3 p_velocity, vec4 p_color, vec4 p_custom, uint p_flags) { \n \t return false; \n } \n " ;
2022-02-20 01:08:53 +01:00
actions . render_mode_defines [ " disable_force " ] = " #define DISABLE_FORCE \n " ;
actions . render_mode_defines [ " disable_velocity " ] = " #define DISABLE_VELOCITY \n " ;
actions . render_mode_defines [ " keep_data " ] = " #define ENABLE_KEEP_DATA \n " ;
2022-09-29 23:56:26 +02:00
actions . render_mode_defines [ " collision_use_scale " ] = " #define USE_COLLISION_SCALE \n " ;
2022-02-20 01:08:53 +01:00
actions . default_filter = ShaderLanguage : : FILTER_LINEAR_MIPMAP ;
actions . default_repeat = ShaderLanguage : : REPEAT_ENABLE ;
2023-01-26 21:14:45 +01:00
actions . global_buffer_array_variable = " global_shader_uniforms " ;
2022-11-08 07:40:03 +01:00
shaders . compiler_particles . initialize ( actions ) ;
2022-02-20 01:08:53 +01:00
}
{
// Setup Sky compiler
ShaderCompiler : : DefaultIdentifierActions actions ;
actions . renames [ " COLOR " ] = " color " ;
actions . renames [ " ALPHA " ] = " alpha " ;
actions . renames [ " EYEDIR " ] = " cube_normal " ;
2022-04-30 00:34:01 +02:00
actions . renames [ " POSITION " ] = " position " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " SKY_COORDS " ] = " panorama_coords " ;
actions . renames [ " SCREEN_UV " ] = " uv " ;
2022-04-30 00:34:01 +02:00
actions . renames [ " TIME " ] = " time " ;
2022-04-29 21:46:29 +02:00
actions . renames [ " FRAGCOORD " ] = " gl_FragCoord " ;
2022-02-20 01:08:53 +01:00
actions . renames [ " PI " ] = _MKSTR ( Math_PI ) ;
actions . renames [ " TAU " ] = _MKSTR ( Math_TAU ) ;
actions . renames [ " E " ] = _MKSTR ( Math_E ) ;
actions . renames [ " HALF_RES_COLOR " ] = " half_res_color " ;
actions . renames [ " QUARTER_RES_COLOR " ] = " quarter_res_color " ;
actions . renames [ " RADIANCE " ] = " radiance " ;
actions . renames [ " FOG " ] = " custom_fog " ;
actions . renames [ " LIGHT0_ENABLED " ] = " directional_lights.data[0].enabled " ;
actions . renames [ " LIGHT0_DIRECTION " ] = " directional_lights.data[0].direction_energy.xyz " ;
actions . renames [ " LIGHT0_ENERGY " ] = " directional_lights.data[0].direction_energy.w " ;
actions . renames [ " LIGHT0_COLOR " ] = " directional_lights.data[0].color_size.xyz " ;
actions . renames [ " LIGHT0_SIZE " ] = " directional_lights.data[0].color_size.w " ;
actions . renames [ " LIGHT1_ENABLED " ] = " directional_lights.data[1].enabled " ;
actions . renames [ " LIGHT1_DIRECTION " ] = " directional_lights.data[1].direction_energy.xyz " ;
actions . renames [ " LIGHT1_ENERGY " ] = " directional_lights.data[1].direction_energy.w " ;
actions . renames [ " LIGHT1_COLOR " ] = " directional_lights.data[1].color_size.xyz " ;
actions . renames [ " LIGHT1_SIZE " ] = " directional_lights.data[1].color_size.w " ;
actions . renames [ " LIGHT2_ENABLED " ] = " directional_lights.data[2].enabled " ;
actions . renames [ " LIGHT2_DIRECTION " ] = " directional_lights.data[2].direction_energy.xyz " ;
actions . renames [ " LIGHT2_ENERGY " ] = " directional_lights.data[2].direction_energy.w " ;
actions . renames [ " LIGHT2_COLOR " ] = " directional_lights.data[2].color_size.xyz " ;
actions . renames [ " LIGHT2_SIZE " ] = " directional_lights.data[2].color_size.w " ;
actions . renames [ " LIGHT3_ENABLED " ] = " directional_lights.data[3].enabled " ;
actions . renames [ " LIGHT3_DIRECTION " ] = " directional_lights.data[3].direction_energy.xyz " ;
actions . renames [ " LIGHT3_ENERGY " ] = " directional_lights.data[3].direction_energy.w " ;
actions . renames [ " LIGHT3_COLOR " ] = " directional_lights.data[3].color_size.xyz " ;
actions . renames [ " LIGHT3_SIZE " ] = " directional_lights.data[3].color_size.w " ;
actions . renames [ " AT_CUBEMAP_PASS " ] = " AT_CUBEMAP_PASS " ;
actions . renames [ " AT_HALF_RES_PASS " ] = " AT_HALF_RES_PASS " ;
actions . renames [ " AT_QUARTER_RES_PASS " ] = " AT_QUARTER_RES_PASS " ;
actions . usage_defines [ " HALF_RES_COLOR " ] = " \n #define USES_HALF_RES_COLOR \n " ;
actions . usage_defines [ " QUARTER_RES_COLOR " ] = " \n #define USES_QUARTER_RES_COLOR \n " ;
actions . render_mode_defines [ " disable_fog " ] = " #define DISABLE_FOG \n " ;
2022-09-13 19:39:04 +02:00
actions . render_mode_defines [ " use_debanding " ] = " #define USE_DEBANDING \n " ;
2022-02-20 01:08:53 +01:00
actions . default_filter = ShaderLanguage : : FILTER_LINEAR_MIPMAP ;
actions . default_repeat = ShaderLanguage : : REPEAT_ENABLE ;
2023-01-26 21:14:45 +01:00
actions . global_buffer_array_variable = " global_shader_uniforms " ;
2022-02-20 01:08:53 +01:00
shaders . compiler_sky . initialize ( actions ) ;
}
2022-03-21 12:25:25 +01:00
}
MaterialStorage : : ~ MaterialStorage ( ) {
2022-02-20 01:08:53 +01:00
//shaders.copy.version_free(shaders.copy_version);
2022-04-03 18:56:43 +02:00
memdelete_arr ( global_shader_uniforms . buffer_values ) ;
memdelete_arr ( global_shader_uniforms . buffer_usage ) ;
memdelete_arr ( global_shader_uniforms . buffer_dirty_regions ) ;
glDeleteBuffers ( 1 , & global_shader_uniforms . buffer ) ;
2022-03-21 12:25:25 +01:00
singleton = nullptr ;
}
2022-04-03 18:56:43 +02:00
/* GLOBAL SHADER UNIFORM API */
2022-03-21 12:25:25 +01:00
2022-04-03 18:56:43 +02:00
int32_t MaterialStorage : : _global_shader_uniform_allocate ( uint32_t p_elements ) {
2022-02-20 01:08:53 +01:00
int32_t idx = 0 ;
2022-04-03 18:56:43 +02:00
while ( idx + p_elements < = global_shader_uniforms . buffer_size ) {
if ( global_shader_uniforms . buffer_usage [ idx ] . elements = = 0 ) {
2022-02-20 01:08:53 +01:00
bool valid = true ;
for ( uint32_t i = 1 ; i < p_elements ; i + + ) {
2022-04-03 18:56:43 +02:00
if ( global_shader_uniforms . buffer_usage [ idx + i ] . elements > 0 ) {
2022-02-20 01:08:53 +01:00
valid = false ;
2022-04-03 18:56:43 +02:00
idx + = i + global_shader_uniforms . buffer_usage [ idx + i ] . elements ;
2022-02-20 01:08:53 +01:00
break ;
}
}
if ( ! valid ) {
continue ; //if not valid, idx is in new position
}
return idx ;
} else {
2022-04-03 18:56:43 +02:00
idx + = global_shader_uniforms . buffer_usage [ idx ] . elements ;
2022-02-20 01:08:53 +01:00
}
}
return - 1 ;
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : _global_shader_uniform_store_in_buffer ( int32_t p_index , RS : : GlobalShaderParameterType p_type , const Variant & p_value ) {
2022-02-20 01:08:53 +01:00
switch ( p_type ) {
case RS : : GLOBAL_VAR_TYPE_BOOL : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
bool b = p_value ;
bv . x = b ? 1.0 : 0.0 ;
bv . y = 0.0 ;
bv . z = 0.0 ;
bv . w = 0.0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_BVEC2 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
uint32_t bvec = p_value ;
bv . x = ( bvec & 1 ) ? 1.0 : 0.0 ;
bv . y = ( bvec & 2 ) ? 1.0 : 0.0 ;
bv . z = 0.0 ;
bv . w = 0.0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_BVEC3 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
uint32_t bvec = p_value ;
bv . x = ( bvec & 1 ) ? 1.0 : 0.0 ;
bv . y = ( bvec & 2 ) ? 1.0 : 0.0 ;
bv . z = ( bvec & 4 ) ? 1.0 : 0.0 ;
bv . w = 0.0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_BVEC4 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
uint32_t bvec = p_value ;
bv . x = ( bvec & 1 ) ? 1.0 : 0.0 ;
bv . y = ( bvec & 2 ) ? 1.0 : 0.0 ;
bv . z = ( bvec & 4 ) ? 1.0 : 0.0 ;
bv . w = ( bvec & 8 ) ? 1.0 : 0.0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_INT : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : ValueInt & bv = * ( GlobalShaderUniforms : : ValueInt * ) & global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
int32_t v = p_value ;
bv . x = v ;
bv . y = 0 ;
bv . z = 0 ;
bv . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_IVEC2 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : ValueInt & bv = * ( GlobalShaderUniforms : : ValueInt * ) & global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Vector2i v = convert_to_vector < Vector2i > ( p_value ) ;
2022-02-20 01:08:53 +01:00
bv . x = v . x ;
bv . y = v . y ;
bv . z = 0 ;
bv . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_IVEC3 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : ValueInt & bv = * ( GlobalShaderUniforms : : ValueInt * ) & global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Vector3i v = convert_to_vector < Vector3i > ( p_value ) ;
2022-02-20 01:08:53 +01:00
bv . x = v . x ;
bv . y = v . y ;
bv . z = v . z ;
bv . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_IVEC4 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : ValueInt & bv = * ( GlobalShaderUniforms : : ValueInt * ) & global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Vector4i v = convert_to_vector < Vector4i > ( p_value ) ;
bv . x = v . x ;
bv . y = v . y ;
bv . z = v . z ;
bv . w = v . w ;
2022-02-20 01:08:53 +01:00
} break ;
case RS : : GLOBAL_VAR_TYPE_RECT2I : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : ValueInt & bv = * ( GlobalShaderUniforms : : ValueInt * ) & global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
Rect2i v = p_value ;
bv . x = v . position . x ;
bv . y = v . position . y ;
bv . z = v . size . x ;
bv . w = v . size . y ;
} break ;
case RS : : GLOBAL_VAR_TYPE_UINT : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : ValueUInt & bv = * ( GlobalShaderUniforms : : ValueUInt * ) & global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
uint32_t v = p_value ;
bv . x = v ;
bv . y = 0 ;
bv . z = 0 ;
bv . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_UVEC2 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : ValueUInt & bv = * ( GlobalShaderUniforms : : ValueUInt * ) & global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Vector2i v = convert_to_vector < Vector2i > ( p_value ) ;
2022-02-20 01:08:53 +01:00
bv . x = v . x ;
bv . y = v . y ;
bv . z = 0 ;
bv . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_UVEC3 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : ValueUInt & bv = * ( GlobalShaderUniforms : : ValueUInt * ) & global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Vector3i v = convert_to_vector < Vector3i > ( p_value ) ;
2022-02-20 01:08:53 +01:00
bv . x = v . x ;
bv . y = v . y ;
bv . z = v . z ;
bv . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_UVEC4 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : ValueUInt & bv = * ( GlobalShaderUniforms : : ValueUInt * ) & global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Vector4i v = convert_to_vector < Vector4i > ( p_value ) ;
bv . x = v . x ;
bv . y = v . y ;
bv . z = v . z ;
bv . w = v . w ;
2022-02-20 01:08:53 +01:00
} break ;
case RS : : GLOBAL_VAR_TYPE_FLOAT : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
float v = p_value ;
bv . x = v ;
bv . y = 0 ;
bv . z = 0 ;
bv . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_VEC2 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Vector2 v = convert_to_vector < Vector2 > ( p_value ) ;
2022-02-20 01:08:53 +01:00
bv . x = v . x ;
bv . y = v . y ;
bv . z = 0 ;
bv . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_VEC3 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Vector3 v = convert_to_vector < Vector3 > ( p_value ) ;
2022-02-20 01:08:53 +01:00
bv . x = v . x ;
bv . y = v . y ;
bv . z = v . z ;
bv . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_VEC4 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Vector4 v = convert_to_vector < Vector4 > ( p_value ) ;
bv . x = v . x ;
bv . y = v . y ;
bv . z = v . z ;
bv . w = v . w ;
2022-02-20 01:08:53 +01:00
} break ;
case RS : : GLOBAL_VAR_TYPE_COLOR : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
Color v = p_value ;
bv . x = v . r ;
bv . y = v . g ;
bv . z = v . b ;
bv . w = v . a ;
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv_linear = global_shader_uniforms . buffer_values [ p_index + 1 ] ;
2022-05-10 19:02:44 +02:00
//v = v.srgb_to_linear();
2022-02-20 01:08:53 +01:00
bv_linear . x = v . r ;
bv_linear . y = v . g ;
bv_linear . z = v . b ;
bv_linear . w = v . a ;
} break ;
case RS : : GLOBAL_VAR_TYPE_RECT2 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value & bv = global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
Rect2 v = p_value ;
bv . x = v . position . x ;
bv . y = v . position . y ;
bv . z = v . size . x ;
bv . w = v . size . y ;
} break ;
case RS : : GLOBAL_VAR_TYPE_MAT2 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value * bv = & global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
Vector < float > m2 = p_value ;
if ( m2 . size ( ) < 4 ) {
m2 . resize ( 4 ) ;
}
bv [ 0 ] . x = m2 [ 0 ] ;
bv [ 0 ] . y = m2 [ 1 ] ;
bv [ 0 ] . z = 0 ;
bv [ 0 ] . w = 0 ;
bv [ 1 ] . x = m2 [ 2 ] ;
bv [ 1 ] . y = m2 [ 3 ] ;
bv [ 1 ] . z = 0 ;
bv [ 1 ] . w = 0 ;
} break ;
case RS : : GLOBAL_VAR_TYPE_MAT3 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value * bv = & global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
Basis v = p_value ;
2023-03-15 07:40:06 +01:00
convert_item_std140 < Basis > ( v , & bv - > x ) ;
2022-02-20 01:08:53 +01:00
} break ;
case RS : : GLOBAL_VAR_TYPE_MAT4 : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value * bv = & global_shader_uniforms . buffer_values [ p_index ] ;
2023-03-15 07:40:06 +01:00
Projection m = p_value ;
convert_item_std140 < Projection > ( m , & bv - > x ) ;
2022-02-20 01:08:53 +01:00
} break ;
case RS : : GLOBAL_VAR_TYPE_TRANSFORM_2D : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value * bv = & global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
Transform2D v = p_value ;
2023-03-15 07:40:06 +01:00
convert_item_std140 < Transform2D > ( v , & bv - > x ) ;
2022-02-20 01:08:53 +01:00
} break ;
case RS : : GLOBAL_VAR_TYPE_TRANSFORM : {
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Value * bv = & global_shader_uniforms . buffer_values [ p_index ] ;
2022-02-20 01:08:53 +01:00
Transform3D v = p_value ;
2023-03-15 07:40:06 +01:00
convert_item_std140 < Transform3D > ( v , & bv - > x ) ;
2022-02-20 01:08:53 +01:00
} break ;
default : {
ERR_FAIL ( ) ;
}
}
}
2022-04-03 18:56:43 +02:00
void MaterialStorage : : _global_shader_uniform_mark_buffer_dirty ( int32_t p_index , int32_t p_elements ) {
2022-02-20 01:08:53 +01:00
int32_t prev_chunk = - 1 ;
for ( int32_t i = 0 ; i < p_elements ; i + + ) {
2022-04-03 18:56:43 +02:00
int32_t chunk = ( p_index + i ) / GlobalShaderUniforms : : BUFFER_DIRTY_REGION_SIZE ;
2022-02-20 01:08:53 +01:00
if ( chunk ! = prev_chunk ) {
2022-04-03 18:56:43 +02:00
if ( ! global_shader_uniforms . buffer_dirty_regions [ chunk ] ) {
global_shader_uniforms . buffer_dirty_regions [ chunk ] = true ;
global_shader_uniforms . buffer_dirty_region_count + + ;
2022-02-20 01:08:53 +01:00
}
}
prev_chunk = chunk ;
}
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : global_shader_parameter_add ( const StringName & p_name , RS : : GlobalShaderParameterType p_type , const Variant & p_value ) {
2022-04-03 18:56:43 +02:00
ERR_FAIL_COND ( global_shader_uniforms . variables . has ( p_name ) ) ;
GlobalShaderUniforms : : Variable gv ;
2022-02-20 01:08:53 +01:00
gv . type = p_type ;
gv . value = p_value ;
gv . buffer_index = - 1 ;
if ( p_type > = RS : : GLOBAL_VAR_TYPE_SAMPLER2D ) {
//is texture
2022-04-03 18:56:43 +02:00
global_shader_uniforms . must_update_texture_materials = true ; //normally there are none
2022-02-20 01:08:53 +01:00
} else {
gv . buffer_elements = 1 ;
if ( p_type = = RS : : GLOBAL_VAR_TYPE_COLOR | | p_type = = RS : : GLOBAL_VAR_TYPE_MAT2 ) {
//color needs to elements to store srgb and linear
gv . buffer_elements = 2 ;
}
if ( p_type = = RS : : GLOBAL_VAR_TYPE_MAT3 | | p_type = = RS : : GLOBAL_VAR_TYPE_TRANSFORM_2D ) {
//color needs to elements to store srgb and linear
gv . buffer_elements = 3 ;
}
if ( p_type = = RS : : GLOBAL_VAR_TYPE_MAT4 | | p_type = = RS : : GLOBAL_VAR_TYPE_TRANSFORM ) {
//color needs to elements to store srgb and linear
gv . buffer_elements = 4 ;
}
//is vector, allocate in buffer and update index
2022-04-03 18:56:43 +02:00
gv . buffer_index = _global_shader_uniform_allocate ( gv . buffer_elements ) ;
2024-06-27 01:57:24 +02:00
ERR_FAIL_COND_MSG ( gv . buffer_index < 0 , vformat ( " Failed allocating global variable '%s' out of buffer memory. Consider increasing rendering/limits/global_shader_variables/buffer_size in the Project Settings. Maximum items supported by this hardware is: %d. " , String ( p_name ) , Config : : get_singleton ( ) - > max_uniform_buffer_size / sizeof ( GlobalShaderUniforms : : Value ) ) ) ;
2022-04-03 18:56:43 +02:00
global_shader_uniforms . buffer_usage [ gv . buffer_index ] . elements = gv . buffer_elements ;
_global_shader_uniform_store_in_buffer ( gv . buffer_index , gv . type , gv . value ) ;
_global_shader_uniform_mark_buffer_dirty ( gv . buffer_index , gv . buffer_elements ) ;
2022-02-20 01:08:53 +01:00
2022-04-03 18:56:43 +02:00
global_shader_uniforms . must_update_buffer_materials = true ; //normally there are none
2022-02-20 01:08:53 +01:00
}
2022-04-03 18:56:43 +02:00
global_shader_uniforms . variables [ p_name ] = gv ;
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : global_shader_parameter_remove ( const StringName & p_name ) {
2022-04-03 18:56:43 +02:00
if ( ! global_shader_uniforms . variables . has ( p_name ) ) {
2022-02-20 01:08:53 +01:00
return ;
}
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Variable & gv = global_shader_uniforms . variables [ p_name ] ;
2022-02-20 01:08:53 +01:00
if ( gv . buffer_index > = 0 ) {
2022-04-03 18:56:43 +02:00
global_shader_uniforms . buffer_usage [ gv . buffer_index ] . elements = 0 ;
global_shader_uniforms . must_update_buffer_materials = true ;
2022-02-20 01:08:53 +01:00
} else {
2022-04-03 18:56:43 +02:00
global_shader_uniforms . must_update_texture_materials = true ;
2022-02-20 01:08:53 +01:00
}
2022-04-03 18:56:43 +02:00
global_shader_uniforms . variables . erase ( p_name ) ;
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
Vector < StringName > MaterialStorage : : global_shader_parameter_get_list ( ) const {
2022-02-20 01:08:53 +01:00
if ( ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
ERR_FAIL_V_MSG ( Vector < StringName > ( ) , " This function should never be used outside the editor, it can severely damage performance. " ) ;
}
Vector < StringName > names ;
2022-04-03 18:56:43 +02:00
for ( const KeyValue < StringName , GlobalShaderUniforms : : Variable > & E : global_shader_uniforms . variables ) {
2022-05-08 10:09:19 +02:00
names . push_back ( E . key ) ;
2022-02-20 01:08:53 +01:00
}
names . sort_custom < StringName : : AlphCompare > ( ) ;
return names ;
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : global_shader_parameter_set ( const StringName & p_name , const Variant & p_value ) {
2022-04-03 18:56:43 +02:00
ERR_FAIL_COND ( ! global_shader_uniforms . variables . has ( p_name ) ) ;
GlobalShaderUniforms : : Variable & gv = global_shader_uniforms . variables [ p_name ] ;
2022-02-20 01:08:53 +01:00
gv . value = p_value ;
if ( gv . override . get_type ( ) = = Variant : : NIL ) {
if ( gv . buffer_index > = 0 ) {
//buffer
2022-04-03 18:56:43 +02:00
_global_shader_uniform_store_in_buffer ( gv . buffer_index , gv . type , gv . value ) ;
_global_shader_uniform_mark_buffer_dirty ( gv . buffer_index , gv . buffer_elements ) ;
2022-02-20 01:08:53 +01:00
} else {
//texture
MaterialStorage * material_storage = MaterialStorage : : get_singleton ( ) ;
2022-05-19 01:43:40 +02:00
for ( const RID & E : gv . texture_materials ) {
Material * material = material_storage - > get_material ( E ) ;
2022-02-20 01:08:53 +01:00
ERR_CONTINUE ( ! material ) ;
material_storage - > _material_queue_update ( material , false , true ) ;
}
}
}
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : global_shader_parameter_set_override ( const StringName & p_name , const Variant & p_value ) {
2022-04-03 18:56:43 +02:00
if ( ! global_shader_uniforms . variables . has ( p_name ) ) {
2022-02-20 01:08:53 +01:00
return ; //variable may not exist
}
ERR_FAIL_COND ( p_value . get_type ( ) = = Variant : : OBJECT ) ;
2022-04-03 18:56:43 +02:00
GlobalShaderUniforms : : Variable & gv = global_shader_uniforms . variables [ p_name ] ;
2022-02-20 01:08:53 +01:00
gv . override = p_value ;
if ( gv . buffer_index > = 0 ) {
//buffer
if ( gv . override . get_type ( ) = = Variant : : NIL ) {
2022-04-03 18:56:43 +02:00
_global_shader_uniform_store_in_buffer ( gv . buffer_index , gv . type , gv . value ) ;
2022-02-20 01:08:53 +01:00
} else {
2022-04-03 18:56:43 +02:00
_global_shader_uniform_store_in_buffer ( gv . buffer_index , gv . type , gv . override ) ;
2022-02-20 01:08:53 +01:00
}
2022-04-03 18:56:43 +02:00
_global_shader_uniform_mark_buffer_dirty ( gv . buffer_index , gv . buffer_elements ) ;
2022-02-20 01:08:53 +01:00
} else {
//texture
MaterialStorage * material_storage = MaterialStorage : : get_singleton ( ) ;
2022-05-19 01:43:40 +02:00
for ( const RID & E : gv . texture_materials ) {
Material * material = material_storage - > get_material ( E ) ;
2022-02-20 01:08:53 +01:00
ERR_CONTINUE ( ! material ) ;
material_storage - > _material_queue_update ( material , false , true ) ;
}
}
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
Variant MaterialStorage : : global_shader_parameter_get ( const StringName & p_name ) const {
2022-02-20 01:08:53 +01:00
if ( ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
ERR_FAIL_V_MSG ( Variant ( ) , " This function should never be used outside the editor, it can severely damage performance. " ) ;
}
2022-04-03 18:56:43 +02:00
if ( ! global_shader_uniforms . variables . has ( p_name ) ) {
2022-02-20 01:08:53 +01:00
return Variant ( ) ;
}
2022-04-03 18:56:43 +02:00
return global_shader_uniforms . variables [ p_name ] . value ;
2022-02-20 01:08:53 +01:00
}
2022-08-27 11:22:43 +02:00
RS : : GlobalShaderParameterType MaterialStorage : : global_shader_parameter_get_type_internal ( const StringName & p_name ) const {
2022-04-03 18:56:43 +02:00
if ( ! global_shader_uniforms . variables . has ( p_name ) ) {
2022-02-20 01:08:53 +01:00
return RS : : GLOBAL_VAR_TYPE_MAX ;
}
2022-04-03 18:56:43 +02:00
return global_shader_uniforms . variables [ p_name ] . type ;
2022-02-20 01:08:53 +01:00
}
2022-08-27 11:22:43 +02:00
RS : : GlobalShaderParameterType MaterialStorage : : global_shader_parameter_get_type ( const StringName & p_name ) const {
2022-02-20 01:08:53 +01:00
if ( ! Engine : : get_singleton ( ) - > is_editor_hint ( ) ) {
ERR_FAIL_V_MSG ( RS : : GLOBAL_VAR_TYPE_MAX , " This function should never be used outside the editor, it can severely damage performance. " ) ;
}
2022-08-27 11:22:43 +02:00
return global_shader_parameter_get_type_internal ( p_name ) ;
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : global_shader_parameters_load_settings ( bool p_load_textures ) {
2022-02-20 01:08:53 +01:00
List < PropertyInfo > settings ;
ProjectSettings : : get_singleton ( ) - > get_property_list ( & settings ) ;
for ( const PropertyInfo & E : settings ) {
if ( E . name . begins_with ( " shader_globals/ " ) ) {
StringName name = E . name . get_slice ( " / " , 1 ) ;
2022-10-18 16:43:37 +02:00
Dictionary d = GLOBAL_GET ( E . name ) ;
2022-02-20 01:08:53 +01:00
ERR_CONTINUE ( ! d . has ( " type " ) ) ;
ERR_CONTINUE ( ! d . has ( " value " ) ) ;
String type = d [ " type " ] ;
static const char * global_var_type_names [ RS : : GLOBAL_VAR_TYPE_MAX ] = {
" bool " ,
" bvec2 " ,
" bvec3 " ,
" bvec4 " ,
" int " ,
" ivec2 " ,
" ivec3 " ,
" ivec4 " ,
" rect2i " ,
" uint " ,
" uvec2 " ,
" uvec3 " ,
" uvec4 " ,
" float " ,
" vec2 " ,
" vec3 " ,
" vec4 " ,
" color " ,
" rect2 " ,
" mat2 " ,
" mat3 " ,
" mat4 " ,
" transform_2d " ,
" transform " ,
" sampler2D " ,
" sampler2DArray " ,
" sampler3D " ,
" samplerCube " ,
} ;
2022-08-27 11:22:43 +02:00
RS : : GlobalShaderParameterType gvtype = RS : : GLOBAL_VAR_TYPE_MAX ;
2022-02-20 01:08:53 +01:00
for ( int i = 0 ; i < RS : : GLOBAL_VAR_TYPE_MAX ; i + + ) {
if ( global_var_type_names [ i ] = = type ) {
2022-08-27 11:22:43 +02:00
gvtype = RS : : GlobalShaderParameterType ( i ) ;
2022-02-20 01:08:53 +01:00
break ;
}
}
ERR_CONTINUE ( gvtype = = RS : : GLOBAL_VAR_TYPE_MAX ) ; //type invalid
Variant value = d [ " value " ] ;
if ( gvtype > = RS : : GLOBAL_VAR_TYPE_SAMPLER2D ) {
String path = value ;
2024-05-01 16:13:14 +02:00
// Don't load the textures, but still add the parameter so shaders compile correctly while loading.
if ( ! p_load_textures | | path . is_empty ( ) ) {
2023-08-15 13:03:37 +02:00
value = RID ( ) ;
} else {
Ref < Resource > resource = ResourceLoader : : load ( path ) ;
value = resource ;
}
2022-02-20 01:08:53 +01:00
}
2022-04-03 18:56:43 +02:00
if ( global_shader_uniforms . variables . has ( name ) ) {
2022-02-20 01:08:53 +01:00
//has it, update it
2022-08-27 11:22:43 +02:00
global_shader_parameter_set ( name , value ) ;
2022-02-20 01:08:53 +01:00
} else {
2022-08-27 11:22:43 +02:00
global_shader_parameter_add ( name , gvtype , value ) ;
2022-02-20 01:08:53 +01:00
}
}
}
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : global_shader_parameters_clear ( ) {
2022-04-03 18:56:43 +02:00
global_shader_uniforms . variables . clear ( ) ;
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
GLuint MaterialStorage : : global_shader_parameters_get_uniform_buffer ( ) const {
2022-04-03 18:56:43 +02:00
return global_shader_uniforms . buffer ;
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
int32_t MaterialStorage : : global_shader_parameters_instance_allocate ( RID p_instance ) {
2022-04-03 18:56:43 +02:00
ERR_FAIL_COND_V ( global_shader_uniforms . instance_buffer_pos . has ( p_instance ) , - 1 ) ;
int32_t pos = _global_shader_uniform_allocate ( ShaderLanguage : : MAX_INSTANCE_UNIFORM_INDICES ) ;
global_shader_uniforms . instance_buffer_pos [ p_instance ] = pos ; //save anyway
2024-06-27 01:57:24 +02:00
ERR_FAIL_COND_V_MSG ( pos < 0 , - 1 , vformat ( " Too many instances using shader instance variables. Consider increasing rendering/limits/global_shader_variables/buffer_size in the Project Settings. Maximum items supported by this hardware is: %d. " , Config : : get_singleton ( ) - > max_uniform_buffer_size / sizeof ( GlobalShaderUniforms : : Value ) ) ) ;
2022-04-03 18:56:43 +02:00
global_shader_uniforms . buffer_usage [ pos ] . elements = ShaderLanguage : : MAX_INSTANCE_UNIFORM_INDICES ;
2022-02-20 01:08:53 +01:00
return pos ;
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : global_shader_parameters_instance_free ( RID p_instance ) {
2022-04-03 18:56:43 +02:00
ERR_FAIL_COND ( ! global_shader_uniforms . instance_buffer_pos . has ( p_instance ) ) ;
int32_t pos = global_shader_uniforms . instance_buffer_pos [ p_instance ] ;
2022-02-20 01:08:53 +01:00
if ( pos > = 0 ) {
2022-04-03 18:56:43 +02:00
global_shader_uniforms . buffer_usage [ pos ] . elements = 0 ;
2022-02-20 01:08:53 +01:00
}
2022-04-03 18:56:43 +02:00
global_shader_uniforms . instance_buffer_pos . erase ( p_instance ) ;
2022-03-21 12:25:25 +01:00
}
2022-10-09 07:14:07 +02:00
void MaterialStorage : : global_shader_parameters_instance_update ( RID p_instance , int p_index , const Variant & p_value , int p_flags_count ) {
2022-04-03 18:56:43 +02:00
if ( ! global_shader_uniforms . instance_buffer_pos . has ( p_instance ) ) {
2022-02-20 01:08:53 +01:00
return ; //just not allocated, ignore
}
2022-04-03 18:56:43 +02:00
int32_t pos = global_shader_uniforms . instance_buffer_pos [ p_instance ] ;
2022-02-20 01:08:53 +01:00
if ( pos < 0 ) {
return ; //again, not allocated, ignore
}
ERR_FAIL_INDEX ( p_index , ShaderLanguage : : MAX_INSTANCE_UNIFORM_INDICES ) ;
2022-10-09 07:14:07 +02:00
Variant : : Type value_type = p_value . get_type ( ) ;
ERR_FAIL_COND_MSG ( p_value . get_type ( ) > Variant : : COLOR , " Unsupported variant type for instance parameter: " + Variant : : get_type_name ( value_type ) ) ; //anything greater not supported
2022-02-20 01:08:53 +01:00
ShaderLanguage : : DataType datatype_from_value [ Variant : : COLOR + 1 ] = {
ShaderLanguage : : TYPE_MAX , //nil
ShaderLanguage : : TYPE_BOOL , //bool
ShaderLanguage : : TYPE_INT , //int
ShaderLanguage : : TYPE_FLOAT , //float
ShaderLanguage : : TYPE_MAX , //string
ShaderLanguage : : TYPE_VEC2 , //vec2
ShaderLanguage : : TYPE_IVEC2 , //vec2i
ShaderLanguage : : TYPE_VEC4 , //rect2
ShaderLanguage : : TYPE_IVEC4 , //rect2i
ShaderLanguage : : TYPE_VEC3 , // vec3
ShaderLanguage : : TYPE_IVEC3 , //vec3i
ShaderLanguage : : TYPE_MAX , //xform2d not supported here
2022-08-01 12:39:51 +02:00
ShaderLanguage : : TYPE_VEC4 , //vec4
ShaderLanguage : : TYPE_IVEC4 , //vec4i
2022-02-20 01:08:53 +01:00
ShaderLanguage : : TYPE_VEC4 , //plane
ShaderLanguage : : TYPE_VEC4 , //quat
ShaderLanguage : : TYPE_MAX , //aabb not supported here
ShaderLanguage : : TYPE_MAX , //basis not supported here
ShaderLanguage : : TYPE_MAX , //xform not supported here
2022-08-01 12:39:51 +02:00
ShaderLanguage : : TYPE_MAX , //projection not supported here
2022-02-20 01:08:53 +01:00
ShaderLanguage : : TYPE_VEC4 //color
} ;
2022-10-09 07:14:07 +02:00
ShaderLanguage : : DataType datatype = ShaderLanguage : : TYPE_MAX ;
if ( value_type = = Variant : : INT & & p_flags_count > 0 ) {
switch ( p_flags_count ) {
case 1 :
datatype = ShaderLanguage : : TYPE_BVEC2 ;
break ;
case 2 :
datatype = ShaderLanguage : : TYPE_BVEC3 ;
break ;
case 3 :
datatype = ShaderLanguage : : TYPE_BVEC4 ;
break ;
}
} else {
datatype = datatype_from_value [ value_type ] ;
}
2022-02-20 01:08:53 +01:00
2022-10-09 07:14:07 +02:00
ERR_FAIL_COND_MSG ( datatype = = ShaderLanguage : : TYPE_MAX , " Unsupported variant type for instance parameter: " + Variant : : get_type_name ( value_type ) ) ; //anything greater not supported
2022-02-20 01:08:53 +01:00
pos + = p_index ;
2022-04-03 18:56:43 +02:00
_fill_std140_variant_ubo_value ( datatype , 0 , p_value , ( uint8_t * ) & global_shader_uniforms . buffer_values [ pos ] ) ;
_global_shader_uniform_mark_buffer_dirty ( pos , 1 ) ;
2022-03-21 12:25:25 +01:00
}
2022-04-03 18:56:43 +02:00
void MaterialStorage : : _update_global_shader_uniforms ( ) {
2022-02-20 01:08:53 +01:00
MaterialStorage * material_storage = MaterialStorage : : get_singleton ( ) ;
2022-04-03 18:56:43 +02:00
if ( global_shader_uniforms . buffer_dirty_region_count > 0 ) {
2024-06-27 01:57:24 +02:00
uint32_t total_regions = 1 + ( global_shader_uniforms . buffer_size / GlobalShaderUniforms : : BUFFER_DIRTY_REGION_SIZE ) ;
2022-04-03 18:56:43 +02:00
if ( total_regions / global_shader_uniforms . buffer_dirty_region_count < = 4 ) {
2022-02-20 01:08:53 +01:00
// 25% of regions dirty, just update all buffer
2022-04-03 18:56:43 +02:00
glBindBuffer ( GL_UNIFORM_BUFFER , global_shader_uniforms . buffer ) ;
glBufferData ( GL_UNIFORM_BUFFER , sizeof ( GlobalShaderUniforms : : Value ) * global_shader_uniforms . buffer_size , global_shader_uniforms . buffer_values , GL_DYNAMIC_DRAW ) ;
2022-02-20 01:08:53 +01:00
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
2022-04-03 18:56:43 +02:00
memset ( global_shader_uniforms . buffer_dirty_regions , 0 , sizeof ( bool ) * total_regions ) ;
2022-02-20 01:08:53 +01:00
} else {
2022-04-03 18:56:43 +02:00
uint32_t region_byte_size = sizeof ( GlobalShaderUniforms : : Value ) * GlobalShaderUniforms : : BUFFER_DIRTY_REGION_SIZE ;
glBindBuffer ( GL_UNIFORM_BUFFER , global_shader_uniforms . buffer ) ;
2022-02-20 01:08:53 +01:00
for ( uint32_t i = 0 ; i < total_regions ; i + + ) {
2022-04-03 18:56:43 +02:00
if ( global_shader_uniforms . buffer_dirty_regions [ i ] ) {
glBufferSubData ( GL_UNIFORM_BUFFER , i * region_byte_size , region_byte_size , & global_shader_uniforms . buffer_values [ i * GlobalShaderUniforms : : BUFFER_DIRTY_REGION_SIZE ] ) ;
global_shader_uniforms . buffer_dirty_regions [ i ] = false ;
2022-02-20 01:08:53 +01:00
}
}
glBindBuffer ( GL_UNIFORM_BUFFER , 0 ) ;
}
2022-03-21 12:25:25 +01:00
2022-04-03 18:56:43 +02:00
global_shader_uniforms . buffer_dirty_region_count = 0 ;
2022-03-21 12:25:25 +01:00
}
2022-04-03 18:56:43 +02:00
if ( global_shader_uniforms . must_update_buffer_materials ) {
2022-02-20 01:08:53 +01:00
// only happens in the case of a buffer variable added or removed,
// so not often.
2022-04-03 18:56:43 +02:00
for ( const RID & E : global_shader_uniforms . materials_using_buffer ) {
2022-02-20 01:08:53 +01:00
Material * material = material_storage - > get_material ( E ) ;
ERR_CONTINUE ( ! material ) ; //wtf
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
material_storage - > _material_queue_update ( material , true , false ) ;
}
2022-04-03 18:56:43 +02:00
global_shader_uniforms . must_update_buffer_materials = false ;
2022-02-20 01:08:53 +01:00
}
2022-04-03 18:56:43 +02:00
if ( global_shader_uniforms . must_update_texture_materials ) {
2022-02-20 01:08:53 +01:00
// only happens in the case of a buffer variable added or removed,
// so not often.
2022-04-03 18:56:43 +02:00
for ( const RID & E : global_shader_uniforms . materials_using_texture ) {
2022-02-20 01:08:53 +01:00
Material * material = material_storage - > get_material ( E ) ;
ERR_CONTINUE ( ! material ) ; //wtf
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
material_storage - > _material_queue_update ( material , false , true ) ;
}
2022-04-03 18:56:43 +02:00
global_shader_uniforms . must_update_texture_materials = false ;
2022-02-20 01:08:53 +01:00
}
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
/* SHADER API */
RID MaterialStorage : : shader_allocate ( ) {
return shader_owner . allocate_rid ( ) ;
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
void MaterialStorage : : shader_initialize ( RID p_rid ) {
Shader shader ;
shader . data = nullptr ;
shader . mode = RS : : SHADER_MAX ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
shader_owner . initialize_rid ( p_rid , shader ) ;
}
2022-03-21 12:25:25 +01:00
void MaterialStorage : : shader_free ( RID p_rid ) {
2022-04-05 06:37:37 +02:00
GLES3 : : Shader * shader = shader_owner . get_or_null ( p_rid ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( shader ) ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
//make material unreference this
while ( shader - > owners . size ( ) ) {
2022-05-19 17:00:06 +02:00
material_set_shader ( ( * shader - > owners . begin ( ) ) - > self , RID ( ) ) ;
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
//clear data if exists
if ( shader - > data ) {
memdelete ( shader - > data ) ;
2022-03-21 12:25:25 +01:00
}
shader_owner . free ( p_rid ) ;
}
void MaterialStorage : : shader_set_code ( RID p_shader , const String & p_code ) {
2022-04-05 06:37:37 +02:00
GLES3 : : Shader * shader = shader_owner . get_or_null ( p_shader ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( shader ) ;
2022-03-21 12:25:25 +01:00
shader - > code = p_code ;
String mode_string = ShaderLanguage : : get_shader_type ( p_code ) ;
2022-02-20 01:08:53 +01:00
RS : : ShaderMode new_mode ;
2022-03-21 12:25:25 +01:00
if ( mode_string = = " canvas_item " ) {
2022-02-20 01:08:53 +01:00
new_mode = RS : : SHADER_CANVAS_ITEM ;
2022-11-08 07:40:03 +01:00
} else if ( mode_string = = " particles " ) {
new_mode = RS : : SHADER_PARTICLES ;
2022-03-21 12:25:25 +01:00
} else if ( mode_string = = " spatial " ) {
2022-02-20 01:08:53 +01:00
new_mode = RS : : SHADER_SPATIAL ;
} else if ( mode_string = = " sky " ) {
new_mode = RS : : SHADER_SKY ;
//} else if (mode_string == "fog") {
// new_mode = RS::SHADER_FOG;
2022-03-21 12:25:25 +01:00
} else {
2022-02-20 01:08:53 +01:00
new_mode = RS : : SHADER_MAX ;
2022-03-21 12:25:25 +01:00
ERR_PRINT ( " shader type " + mode_string + " not supported in OpenGL renderer " ) ;
}
2022-02-20 01:08:53 +01:00
if ( new_mode ! = shader - > mode ) {
if ( shader - > data ) {
memdelete ( shader - > data ) ;
shader - > data = nullptr ;
}
2022-05-19 01:43:40 +02:00
for ( Material * E : shader - > owners ) {
Material * material = E ;
2022-02-20 01:08:53 +01:00
material - > shader_mode = new_mode ;
if ( material - > data ) {
memdelete ( material - > data ) ;
material - > data = nullptr ;
}
}
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
shader - > mode = new_mode ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
if ( new_mode < RS : : SHADER_MAX & & shader_data_request_func [ new_mode ] ) {
shader - > data = shader_data_request_func [ new_mode ] ( ) ;
} else {
shader - > mode = RS : : SHADER_MAX ; //invalid
}
2022-05-19 01:43:40 +02:00
for ( Material * E : shader - > owners ) {
Material * material = E ;
2022-02-20 01:08:53 +01:00
if ( shader - > data ) {
material - > data = material_data_request_func [ new_mode ] ( shader - > data ) ;
material - > data - > self = material - > self ;
material - > data - > set_next_pass ( material - > next_pass ) ;
material - > data - > set_render_priority ( material - > priority ) ;
}
material - > shader_mode = new_mode ;
}
if ( shader - > data ) {
2022-05-13 15:04:37 +02:00
for ( const KeyValue < StringName , HashMap < int , RID > > & E : shader - > default_texture_parameter ) {
2022-02-20 01:08:53 +01:00
for ( const KeyValue < int , RID > & E2 : E . value ) {
2022-08-27 11:22:43 +02:00
shader - > data - > set_default_texture_parameter ( E . key , E2 . value , E2 . key ) ;
2022-02-20 01:08:53 +01:00
}
}
}
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
if ( shader - > data ) {
shader - > data - > set_code ( p_code ) ;
2022-03-21 12:25:25 +01:00
}
2022-05-19 01:43:40 +02:00
for ( Material * E : shader - > owners ) {
Material * material = E ;
2022-06-21 02:08:33 +02:00
material - > dependency . changed_notify ( Dependency : : DEPENDENCY_CHANGED_MATERIAL ) ;
2022-02-20 01:08:53 +01:00
_material_queue_update ( material , true , true ) ;
}
2022-03-21 12:25:25 +01:00
}
2022-06-29 11:31:18 +02:00
void MaterialStorage : : shader_set_path_hint ( RID p_shader , const String & p_path ) {
GLES3 : : Shader * shader = shader_owner . get_or_null ( p_shader ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( shader ) ;
2022-06-29 11:31:18 +02:00
shader - > path_hint = p_path ;
2022-11-08 07:40:03 +01:00
if ( shader - > data ) {
shader - > data - > set_path_hint ( p_path ) ;
}
2022-06-29 11:31:18 +02:00
}
2022-03-21 12:25:25 +01:00
String MaterialStorage : : shader_get_code ( RID p_shader ) const {
2022-04-05 06:37:37 +02:00
const GLES3 : : Shader * shader = shader_owner . get_or_null ( p_shader ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL_V ( shader , String ( ) ) ;
2022-03-21 12:25:25 +01:00
return shader - > code ;
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : get_shader_parameter_list ( RID p_shader , List < PropertyInfo > * p_param_list ) const {
2022-04-05 06:37:37 +02:00
GLES3 : : Shader * shader = shader_owner . get_or_null ( p_shader ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( shader ) ;
2022-02-20 01:08:53 +01:00
if ( shader - > data ) {
2022-04-03 19:09:09 +02:00
return shader - > data - > get_shader_uniform_list ( p_param_list ) ;
2022-03-21 12:25:25 +01:00
}
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : shader_set_default_texture_parameter ( RID p_shader , const StringName & p_name , RID p_texture , int p_index ) {
2022-04-05 06:37:37 +02:00
GLES3 : : Shader * shader = shader_owner . get_or_null ( p_shader ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( shader ) ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
if ( p_texture . is_valid ( ) & & TextureStorage : : get_singleton ( ) - > owns_texture ( p_texture ) ) {
if ( ! shader - > default_texture_parameter . has ( p_name ) ) {
2022-05-13 15:04:37 +02:00
shader - > default_texture_parameter [ p_name ] = HashMap < int , RID > ( ) ;
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
shader - > default_texture_parameter [ p_name ] [ p_index ] = p_texture ;
2022-03-21 12:25:25 +01:00
} else {
2022-02-20 01:08:53 +01:00
if ( shader - > default_texture_parameter . has ( p_name ) & & shader - > default_texture_parameter [ p_name ] . has ( p_index ) ) {
shader - > default_texture_parameter [ p_name ] . erase ( p_index ) ;
if ( shader - > default_texture_parameter [ p_name ] . is_empty ( ) ) {
shader - > default_texture_parameter . erase ( p_name ) ;
}
2022-03-21 12:25:25 +01:00
}
}
2022-02-20 01:08:53 +01:00
if ( shader - > data ) {
2022-08-27 11:22:43 +02:00
shader - > data - > set_default_texture_parameter ( p_name , p_texture , p_index ) ;
2022-02-20 01:08:53 +01:00
}
2022-05-19 01:43:40 +02:00
for ( Material * E : shader - > owners ) {
Material * material = E ;
2022-02-20 01:08:53 +01:00
_material_queue_update ( material , false , true ) ;
}
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
RID MaterialStorage : : shader_get_default_texture_parameter ( RID p_shader , const StringName & p_name , int p_index ) const {
2022-04-05 06:37:37 +02:00
const GLES3 : : Shader * shader = shader_owner . get_or_null ( p_shader ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL_V ( shader , RID ( ) ) ;
2022-02-20 01:08:53 +01:00
if ( shader - > default_texture_parameter . has ( p_name ) & & shader - > default_texture_parameter [ p_name ] . has ( p_index ) ) {
return shader - > default_texture_parameter [ p_name ] [ p_index ] ;
2022-03-21 12:25:25 +01:00
}
return RID ( ) ;
}
2022-08-27 11:22:43 +02:00
Variant MaterialStorage : : shader_get_parameter_default ( RID p_shader , const StringName & p_param ) const {
2022-02-20 01:08:53 +01:00
Shader * shader = shader_owner . get_or_null ( p_shader ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL_V ( shader , Variant ( ) ) ;
2022-02-20 01:08:53 +01:00
if ( shader - > data ) {
return shader - > data - > get_default_parameter ( p_param ) ;
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
return Variant ( ) ;
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
RS : : ShaderNativeSourceCode MaterialStorage : : shader_get_native_source_code ( RID p_shader ) const {
Shader * shader = shader_owner . get_or_null ( p_shader ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL_V ( shader , RS : : ShaderNativeSourceCode ( ) ) ;
2022-02-20 01:08:53 +01:00
if ( shader - > data ) {
return shader - > data - > get_native_source_code ( ) ;
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
return RS : : ShaderNativeSourceCode ( ) ;
2022-03-21 12:25:25 +01:00
}
/* MATERIAL API */
2022-05-09 01:25:49 +02:00
void MaterialStorage : : _material_queue_update ( GLES3 : : Material * material , bool p_uniform , bool p_texture ) {
2022-02-20 01:08:53 +01:00
material - > uniform_dirty = material - > uniform_dirty | | p_uniform ;
material - > texture_dirty = material - > texture_dirty | | p_texture ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
if ( material - > update_element . in_list ( ) ) {
2022-03-21 12:25:25 +01:00
return ;
}
2022-02-20 01:08:53 +01:00
material_update_list . add ( & material - > update_element ) ;
}
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
void MaterialStorage : : _update_queued_materials ( ) {
while ( material_update_list . first ( ) ) {
Material * material = material_update_list . first ( ) - > self ( ) ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
if ( material - > data ) {
material - > data - > update_parameters ( material - > params , material - > uniform_dirty , material - > texture_dirty ) ;
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
material - > texture_dirty = false ;
material - > uniform_dirty = false ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
material_update_list . remove ( & material - > update_element ) ;
2022-03-21 12:25:25 +01:00
}
}
RID MaterialStorage : : material_allocate ( ) {
2022-02-20 01:08:53 +01:00
return material_owner . allocate_rid ( ) ;
2022-03-21 12:25:25 +01:00
}
void MaterialStorage : : material_initialize ( RID p_rid ) {
2022-02-20 01:08:53 +01:00
material_owner . initialize_rid ( p_rid ) ;
Material * material = material_owner . get_or_null ( p_rid ) ;
material - > self = p_rid ;
2022-03-21 12:25:25 +01:00
}
void MaterialStorage : : material_free ( RID p_rid ) {
2022-02-20 01:08:53 +01:00
Material * material = material_owner . get_or_null ( p_rid ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( material ) ;
2022-03-21 12:25:25 +01:00
2023-01-13 19:14:00 +01:00
// Need to clear texture arrays to prevent spin locking of their RID's.
// This happens when the app is being closed.
for ( KeyValue < StringName , Variant > & E : material - > params ) {
if ( E . value . get_type ( ) = = Variant : : ARRAY ) {
Array ( E . value ) . clear ( ) ;
}
}
2022-02-20 01:08:53 +01:00
material_set_shader ( p_rid , RID ( ) ) ; //clean up shader
material - > dependency . deleted_notify ( p_rid ) ;
2022-03-21 12:25:25 +01:00
material_owner . free ( p_rid ) ;
}
void MaterialStorage : : material_set_shader ( RID p_material , RID p_shader ) {
2022-04-05 06:37:37 +02:00
GLES3 : : Material * material = material_owner . get_or_null ( p_material ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( material ) ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
if ( material - > data ) {
memdelete ( material - > data ) ;
material - > data = nullptr ;
}
2022-03-21 12:25:25 +01:00
if ( material - > shader ) {
2022-02-20 01:08:53 +01:00
material - > shader - > owners . erase ( material ) ;
material - > shader = nullptr ;
material - > shader_mode = RS : : SHADER_MAX ;
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
if ( p_shader . is_null ( ) ) {
2022-06-21 02:08:33 +02:00
material - > dependency . changed_notify ( Dependency : : DEPENDENCY_CHANGED_MATERIAL ) ;
2022-02-20 01:08:53 +01:00
material - > shader_id = 0 ;
return ;
}
Shader * shader = get_shader ( p_shader ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( shader ) ;
2022-03-21 12:25:25 +01:00
material - > shader = shader ;
2022-02-20 01:08:53 +01:00
material - > shader_mode = shader - > mode ;
material - > shader_id = p_shader . get_local_index ( ) ;
shader - > owners . insert ( material ) ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
if ( shader - > mode = = RS : : SHADER_MAX ) {
return ;
2022-03-21 12:25:25 +01:00
}
2023-09-28 11:40:18 +02:00
ERR_FAIL_NULL ( shader - > data ) ;
2022-02-20 01:08:53 +01:00
material - > data = material_data_request_func [ shader - > mode ] ( shader - > data ) ;
material - > data - > self = p_material ;
material - > data - > set_next_pass ( material - > next_pass ) ;
material - > data - > set_render_priority ( material - > priority ) ;
//updating happens later
2022-06-21 02:08:33 +02:00
material - > dependency . changed_notify ( Dependency : : DEPENDENCY_CHANGED_MATERIAL ) ;
2022-02-20 01:08:53 +01:00
_material_queue_update ( material , true , true ) ;
2022-03-21 12:25:25 +01:00
}
void MaterialStorage : : material_set_param ( RID p_material , const StringName & p_param , const Variant & p_value ) {
2022-04-05 06:37:37 +02:00
GLES3 : : Material * material = material_owner . get_or_null ( p_material ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( material ) ;
2022-03-21 12:25:25 +01:00
if ( p_value . get_type ( ) = = Variant : : NIL ) {
material - > params . erase ( p_param ) ;
} else {
2022-02-20 01:08:53 +01:00
ERR_FAIL_COND ( p_value . get_type ( ) = = Variant : : OBJECT ) ; //object not allowed
2022-03-21 12:25:25 +01:00
material - > params [ p_param ] = p_value ;
}
2022-02-20 01:08:53 +01:00
if ( material - > shader & & material - > shader - > data ) { //shader is valid
2022-08-27 11:22:43 +02:00
bool is_texture = material - > shader - > data - > is_parameter_texture ( p_param ) ;
2022-02-20 01:08:53 +01:00
_material_queue_update ( material , ! is_texture , is_texture ) ;
} else {
_material_queue_update ( material , true , true ) ;
}
2022-03-21 12:25:25 +01:00
}
Variant MaterialStorage : : material_get_param ( RID p_material , const StringName & p_param ) const {
2022-04-05 06:37:37 +02:00
const GLES3 : : Material * material = material_owner . get_or_null ( p_material ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL_V ( material , Variant ( ) ) ;
2022-03-21 12:25:25 +01:00
if ( material - > params . has ( p_param ) ) {
return material - > params [ p_param ] ;
2022-02-20 01:08:53 +01:00
} else {
return Variant ( ) ;
2022-03-21 12:25:25 +01:00
}
}
void MaterialStorage : : material_set_next_pass ( RID p_material , RID p_next_material ) {
2022-04-05 06:37:37 +02:00
GLES3 : : Material * material = material_owner . get_or_null ( p_material ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( material ) ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
if ( material - > next_pass = = p_next_material ) {
return ;
}
2022-03-21 12:25:25 +01:00
material - > next_pass = p_next_material ;
2022-02-20 01:08:53 +01:00
if ( material - > data ) {
material - > data - > set_next_pass ( p_next_material ) ;
}
2022-06-21 02:08:33 +02:00
material - > dependency . changed_notify ( Dependency : : DEPENDENCY_CHANGED_MATERIAL ) ;
2022-03-21 12:25:25 +01:00
}
void MaterialStorage : : material_set_render_priority ( RID p_material , int priority ) {
ERR_FAIL_COND ( priority < RS : : MATERIAL_RENDER_PRIORITY_MIN ) ;
ERR_FAIL_COND ( priority > RS : : MATERIAL_RENDER_PRIORITY_MAX ) ;
2022-04-05 06:37:37 +02:00
GLES3 : : Material * material = material_owner . get_or_null ( p_material ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( material ) ;
2022-02-20 01:08:53 +01:00
material - > priority = priority ;
if ( material - > data ) {
material - > data - > set_render_priority ( priority ) ;
}
2023-02-14 03:09:33 +01:00
material - > dependency . changed_notify ( Dependency : : DEPENDENCY_CHANGED_MATERIAL ) ;
2022-03-21 12:25:25 +01:00
}
bool MaterialStorage : : material_is_animated ( RID p_material ) {
2022-04-05 06:37:37 +02:00
GLES3 : : Material * material = material_owner . get_or_null ( p_material ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL_V ( material , false ) ;
2022-02-20 01:08:53 +01:00
if ( material - > shader & & material - > shader - > data ) {
if ( material - > shader - > data - > is_animated ( ) ) {
return true ;
} else if ( material - > next_pass . is_valid ( ) ) {
return material_is_animated ( material - > next_pass ) ;
}
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
return false ; //by default nothing is animated
2022-03-21 12:25:25 +01:00
}
bool MaterialStorage : : material_casts_shadows ( RID p_material ) {
2022-04-05 06:37:37 +02:00
GLES3 : : Material * material = material_owner . get_or_null ( p_material ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL_V ( material , true ) ;
2022-02-20 01:08:53 +01:00
if ( material - > shader & & material - > shader - > data ) {
if ( material - > shader - > data - > casts_shadows ( ) ) {
return true ;
} else if ( material - > next_pass . is_valid ( ) ) {
return material_casts_shadows ( material - > next_pass ) ;
}
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
return true ; //by default everything casts shadows
2022-03-21 12:25:25 +01:00
}
2022-08-27 11:22:43 +02:00
void MaterialStorage : : material_get_instance_shader_parameters ( RID p_material , List < InstanceShaderParam > * r_parameters ) {
2022-02-20 01:08:53 +01:00
GLES3 : : Material * material = material_owner . get_or_null ( p_material ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( material ) ;
2022-02-20 01:08:53 +01:00
if ( material - > shader & & material - > shader - > data ) {
material - > shader - > data - > get_instance_param_list ( r_parameters ) ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
if ( material - > next_pass . is_valid ( ) ) {
2022-08-27 11:22:43 +02:00
material_get_instance_shader_parameters ( material - > next_pass , r_parameters ) ;
2022-03-21 12:25:25 +01:00
}
}
}
2022-06-21 02:08:33 +02:00
void MaterialStorage : : material_update_dependency ( RID p_material , DependencyTracker * p_instance ) {
2022-02-20 01:08:53 +01:00
Material * material = material_owner . get_or_null ( p_material ) ;
2023-09-09 17:46:44 +02:00
ERR_FAIL_NULL ( material ) ;
2022-02-20 01:08:53 +01:00
p_instance - > update_dependency ( & material - > dependency ) ;
if ( material - > next_pass . is_valid ( ) ) {
material_update_dependency ( material - > next_pass , p_instance ) ;
2022-03-21 12:25:25 +01:00
}
}
2023-03-25 10:46:33 +01:00
LocalVector < ShaderGLES3 : : TextureUniformData > get_texture_uniform_data ( const Vector < ShaderCompiler : : GeneratedCode : : Texture > & texture_uniforms ) {
LocalVector < ShaderGLES3 : : TextureUniformData > texture_uniform_data ;
for ( int i = 0 ; i < texture_uniforms . size ( ) ; i + + ) {
int num_textures = texture_uniforms [ i ] . array_size ;
if ( num_textures = = 0 ) {
num_textures = 1 ;
}
texture_uniform_data . push_back ( { texture_uniforms [ i ] . name , num_textures } ) ;
}
return texture_uniform_data ;
}
2022-04-30 00:34:01 +02:00
/* Canvas Shader Data */
2022-02-20 01:08:53 +01:00
void CanvasShaderData : : set_code ( const String & p_code ) {
2023-11-11 15:13:23 +01:00
// Initialize and compile the shader.
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
code = p_code ;
valid = false ;
ubo_size = 0 ;
uniforms . clear ( ) ;
2023-11-11 15:13:23 +01:00
2022-02-20 01:08:53 +01:00
uses_screen_texture = false ;
2022-08-09 18:29:49 +02:00
uses_screen_texture_mipmaps = false ;
2022-02-20 01:08:53 +01:00
uses_sdf = false ;
uses_time = false ;
2023-12-27 21:58:50 +01:00
uses_custom0 = false ;
uses_custom1 = false ;
2022-02-20 01:08:53 +01:00
if ( code . is_empty ( ) ) {
2023-11-11 15:13:23 +01:00
return ; // Just invalid, but no error.
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
ShaderCompiler : : GeneratedCode gen_code ;
2022-03-21 12:25:25 +01:00
2023-11-11 15:13:23 +01:00
// Actual enum set further down after compilation.
2022-05-18 17:04:41 +02:00
int blend_modei = BLEND_MODE_MIX ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
ShaderCompiler : : IdentifierActions actions ;
actions . entry_point_stages [ " vertex " ] = ShaderCompiler : : STAGE_VERTEX ;
actions . entry_point_stages [ " fragment " ] = ShaderCompiler : : STAGE_FRAGMENT ;
actions . entry_point_stages [ " light " ] = ShaderCompiler : : STAGE_FRAGMENT ;
2022-03-21 12:25:25 +01:00
2022-05-18 17:04:41 +02:00
actions . render_mode_values [ " blend_add " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_ADD ) ;
actions . render_mode_values [ " blend_mix " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_MIX ) ;
actions . render_mode_values [ " blend_sub " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_SUB ) ;
actions . render_mode_values [ " blend_mul " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_MUL ) ;
actions . render_mode_values [ " blend_premul_alpha " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_PMALPHA ) ;
actions . render_mode_values [ " blend_disabled " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_DISABLED ) ;
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
actions . usage_flag_pointers [ " texture_sdf " ] = & uses_sdf ;
actions . usage_flag_pointers [ " TIME " ] = & uses_time ;
2023-12-27 21:58:50 +01:00
actions . usage_flag_pointers [ " CUSTOM0 " ] = & uses_custom0 ;
actions . usage_flag_pointers [ " CUSTOM1 " ] = & uses_custom1 ;
2022-02-20 01:08:53 +01:00
actions . uniforms = & uniforms ;
Error err = MaterialStorage : : get_singleton ( ) - > shaders . compiler_canvas . compile ( RS : : SHADER_CANVAS_ITEM , code , & actions , path , gen_code ) ;
ERR_FAIL_COND_MSG ( err ! = OK , " Shader compilation failed. " ) ;
if ( version . is_null ( ) ) {
version = MaterialStorage : : get_singleton ( ) - > shaders . canvas_shader . version_create ( ) ;
}
2022-05-18 17:04:41 +02:00
blend_mode = BlendMode ( blend_modei ) ;
2023-01-05 20:55:59 +01:00
uses_screen_texture = gen_code . uses_screen_texture ;
2023-11-11 15:13:23 +01:00
uses_screen_texture_mipmaps = gen_code . uses_screen_texture_mipmaps ;
2022-05-18 17:04:41 +02:00
2022-02-20 01:08:53 +01:00
#if 0
print_line ( " **compiling shader: " ) ;
print_line ( " **defines: \n " ) ;
for ( int i = 0 ; i < gen_code . defines . size ( ) ; i + + ) {
print_line ( gen_code . defines [ i ] ) ;
2022-03-21 12:25:25 +01:00
}
2022-08-09 18:29:49 +02:00
HashMap < String , String > : : Iterator el = gen_code . code . begin ( ) ;
while ( el ) {
print_line ( " \n **code " + el - > key + " : \n " + el - > value ) ;
+ + el ;
}
2022-02-20 01:08:53 +01:00
print_line ( " \n **uniforms: \n " + gen_code . uniforms ) ;
2022-08-09 18:29:49 +02:00
print_line ( " \n **vertex_globals: \n " + gen_code . stage_globals [ ShaderCompiler : : STAGE_VERTEX ] ) ;
print_line ( " \n **fragment_globals: \n " + gen_code . stage_globals [ ShaderCompiler : : STAGE_FRAGMENT ] ) ;
2022-02-20 01:08:53 +01:00
# endif
2022-03-21 12:25:25 +01:00
2023-03-25 10:46:33 +01:00
LocalVector < ShaderGLES3 : : TextureUniformData > texture_uniform_data = get_texture_uniform_data ( gen_code . texture_uniforms ) ;
2022-03-21 12:25:25 +01:00
2023-03-25 10:46:33 +01:00
MaterialStorage : : get_singleton ( ) - > shaders . canvas_shader . version_set_code ( version , gen_code . code , gen_code . uniforms , gen_code . stage_globals [ ShaderCompiler : : STAGE_VERTEX ] , gen_code . stage_globals [ ShaderCompiler : : STAGE_FRAGMENT ] , gen_code . defines , texture_uniform_data ) ;
2022-02-20 01:08:53 +01:00
ERR_FAIL_COND ( ! MaterialStorage : : get_singleton ( ) - > shaders . canvas_shader . version_is_valid ( version ) ) ;
2024-02-28 00:39:20 +01:00
vertex_input_mask = RS : : ARRAY_FORMAT_VERTEX | RS : : ARRAY_FORMAT_COLOR | RS : : ARRAY_FORMAT_TEX_UV ;
2023-12-27 21:58:50 +01:00
vertex_input_mask | = uses_custom0 < < RS : : ARRAY_CUSTOM0 ;
vertex_input_mask | = uses_custom1 < < RS : : ARRAY_CUSTOM1 ;
2022-02-20 01:08:53 +01:00
ubo_size = gen_code . uniform_total_size ;
ubo_offsets = gen_code . uniform_offsets ;
texture_uniforms = gen_code . texture_uniforms ;
valid = true ;
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
bool CanvasShaderData : : is_animated ( ) const {
return false ;
}
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
bool CanvasShaderData : : casts_shadows ( ) const {
return false ;
}
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
RS : : ShaderNativeSourceCode CanvasShaderData : : get_native_source_code ( ) const {
return MaterialStorage : : get_singleton ( ) - > shaders . canvas_shader . version_get_native_source_code ( version ) ;
}
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
CanvasShaderData : : CanvasShaderData ( ) {
valid = false ;
uses_screen_texture = false ;
uses_sdf = false ;
}
2022-03-21 12:25:25 +01:00
2022-02-20 01:08:53 +01:00
CanvasShaderData : : ~ CanvasShaderData ( ) {
if ( version . is_valid ( ) ) {
MaterialStorage : : get_singleton ( ) - > shaders . canvas_shader . version_free ( version ) ;
2022-03-21 12:25:25 +01:00
}
}
2022-02-20 01:08:53 +01:00
GLES3 : : ShaderData * GLES3 : : _create_canvas_shader_func ( ) {
CanvasShaderData * shader_data = memnew ( CanvasShaderData ) ;
return shader_data ;
}
2022-03-21 12:25:25 +01:00
2022-05-13 15:04:37 +02:00
void CanvasMaterialData : : update_parameters ( const HashMap < StringName , Variant > & p_parameters , bool p_uniform_dirty , bool p_textures_dirty ) {
2023-06-13 22:20:11 +02:00
update_parameters_internal ( p_parameters , p_uniform_dirty , p_textures_dirty , shader_data - > uniforms , shader_data - > ubo_offsets . ptr ( ) , shader_data - > texture_uniforms , shader_data - > default_texture_params , shader_data - > ubo_size , false ) ;
2022-02-20 01:08:53 +01:00
}
2022-03-21 12:25:25 +01:00
2023-03-25 10:46:33 +01:00
static void bind_uniforms_generic ( const Vector < RID > & p_textures , const Vector < ShaderCompiler : : GeneratedCode : : Texture > & p_texture_uniforms , int texture_offset = 0 , const RS : : CanvasItemTextureFilter * filter_mapping = filter_from_uniform , const RS : : CanvasItemTextureRepeat * repeat_mapping = repeat_from_uniform ) {
const RID * textures = p_textures . ptr ( ) ;
const ShaderCompiler : : GeneratedCode : : Texture * texture_uniforms = p_texture_uniforms . ptr ( ) ;
int texture_uniform_index = 0 ;
int texture_uniform_count = 0 ;
for ( int ti = 0 ; ti < p_textures . size ( ) ; ti + + ) {
ERR_FAIL_COND_MSG ( texture_uniform_index > = p_texture_uniforms . size ( ) , " texture_uniform_index out of bounds " ) ;
GLES3 : : Texture * texture = TextureStorage : : get_singleton ( ) - > get_texture ( textures [ ti ] ) ;
const ShaderCompiler : : GeneratedCode : : Texture & texture_uniform = texture_uniforms [ texture_uniform_index ] ;
if ( texture ) {
glActiveTexture ( GL_TEXTURE0 + texture_offset + ti ) ;
glBindTexture ( target_from_type [ texture_uniform . type ] , texture - > tex_id ) ;
if ( texture - > render_target ) {
texture - > render_target - > used_in_frame = true ;
}
texture - > gl_set_filter ( filter_mapping [ int ( texture_uniform . filter ) ] ) ;
texture - > gl_set_repeat ( repeat_mapping [ int ( texture_uniform . repeat ) ] ) ;
}
texture_uniform_count + + ;
if ( texture_uniform_count > = texture_uniform . array_size ) {
texture_uniform_index + + ;
texture_uniform_count = 0 ;
}
}
}
2022-02-20 01:08:53 +01:00
void CanvasMaterialData : : bind_uniforms ( ) {
// Bind Material Uniforms
2022-05-10 19:02:44 +02:00
glBindBufferBase ( GL_UNIFORM_BUFFER , RasterizerCanvasGLES3 : : MATERIAL_UNIFORM_LOCATION , uniform_buffer ) ;
2022-02-20 01:08:53 +01:00
2023-03-25 10:46:33 +01:00
bind_uniforms_generic ( texture_cache , shader_data - > texture_uniforms , 1 , filter_from_uniform_canvas , repeat_from_uniform_canvas ) ; // Start at GL_TEXTURE1 because texture slot 0 is used by the base texture
2022-03-21 12:25:25 +01:00
}
2022-02-20 01:08:53 +01:00
CanvasMaterialData : : ~ CanvasMaterialData ( ) {
}
GLES3 : : MaterialData * GLES3 : : _create_canvas_material_func ( ShaderData * p_shader ) {
CanvasMaterialData * material_data = memnew ( CanvasMaterialData ) ;
material_data - > shader_data = static_cast < CanvasShaderData * > ( p_shader ) ;
//update will happen later anyway so do nothing.
return material_data ;
}
2022-03-21 12:25:25 +01:00
2022-04-30 00:34:01 +02:00
////////////////////////////////////////////////////////////////////////////////
// SKY SHADER
void SkyShaderData : : set_code ( const String & p_code ) {
2023-11-11 15:13:23 +01:00
// Initialize and compile the shader.
2022-04-30 00:34:01 +02:00
code = p_code ;
valid = false ;
ubo_size = 0 ;
uniforms . clear ( ) ;
2023-11-11 15:13:23 +01:00
uses_time = false ;
uses_position = false ;
uses_half_res = false ;
uses_quarter_res = false ;
uses_light = false ;
2022-04-30 00:34:01 +02:00
if ( code . is_empty ( ) ) {
2023-11-11 15:13:23 +01:00
return ; // Just invalid, but no error.
2022-04-30 00:34:01 +02:00
}
ShaderCompiler : : GeneratedCode gen_code ;
2023-11-11 15:13:23 +01:00
2022-04-30 00:34:01 +02:00
ShaderCompiler : : IdentifierActions actions ;
actions . entry_point_stages [ " sky " ] = ShaderCompiler : : STAGE_FRAGMENT ;
actions . render_mode_flags [ " use_half_res_pass " ] = & uses_half_res ;
actions . render_mode_flags [ " use_quarter_res_pass " ] = & uses_quarter_res ;
actions . usage_flag_pointers [ " TIME " ] = & uses_time ;
actions . usage_flag_pointers [ " POSITION " ] = & uses_position ;
actions . usage_flag_pointers [ " LIGHT0_ENABLED " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT0_ENERGY " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT0_DIRECTION " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT0_COLOR " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT0_SIZE " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT1_ENABLED " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT1_ENERGY " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT1_DIRECTION " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT1_COLOR " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT1_SIZE " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT2_ENABLED " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT2_ENERGY " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT2_DIRECTION " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT2_COLOR " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT2_SIZE " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT3_ENABLED " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT3_ENERGY " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT3_DIRECTION " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT3_COLOR " ] = & uses_light ;
actions . usage_flag_pointers [ " LIGHT3_SIZE " ] = & uses_light ;
actions . uniforms = & uniforms ;
Error err = MaterialStorage : : get_singleton ( ) - > shaders . compiler_sky . compile ( RS : : SHADER_SKY , code , & actions , path , gen_code ) ;
ERR_FAIL_COND_MSG ( err ! = OK , " Shader compilation failed. " ) ;
if ( version . is_null ( ) ) {
version = MaterialStorage : : get_singleton ( ) - > shaders . sky_shader . version_create ( ) ;
}
#if 0
print_line ( " **compiling shader: " ) ;
print_line ( " **defines: \n " ) ;
for ( int i = 0 ; i < gen_code . defines . size ( ) ; i + + ) {
print_line ( gen_code . defines [ i ] ) ;
}
2022-08-09 18:29:49 +02:00
HashMap < String , String > : : Iterator el = gen_code . code . begin ( ) ;
while ( el ) {
print_line ( " \n **code " + el - > key + " : \n " + el - > value ) ;
+ + el ;
}
2022-04-30 00:34:01 +02:00
print_line ( " \n **uniforms: \n " + gen_code . uniforms ) ;
2022-08-09 18:29:49 +02:00
print_line ( " \n **vertex_globals: \n " + gen_code . stage_globals [ ShaderCompiler : : STAGE_VERTEX ] ) ;
print_line ( " \n **fragment_globals: \n " + gen_code . stage_globals [ ShaderCompiler : : STAGE_FRAGMENT ] ) ;
2022-04-30 00:34:01 +02:00
# endif
2023-03-25 10:46:33 +01:00
LocalVector < ShaderGLES3 : : TextureUniformData > texture_uniform_data = get_texture_uniform_data ( gen_code . texture_uniforms ) ;
2022-04-30 00:34:01 +02:00
2023-03-25 10:46:33 +01:00
MaterialStorage : : get_singleton ( ) - > shaders . sky_shader . version_set_code ( version , gen_code . code , gen_code . uniforms , gen_code . stage_globals [ ShaderCompiler : : STAGE_VERTEX ] , gen_code . stage_globals [ ShaderCompiler : : STAGE_FRAGMENT ] , gen_code . defines , texture_uniform_data ) ;
2022-04-30 00:34:01 +02:00
ERR_FAIL_COND ( ! MaterialStorage : : get_singleton ( ) - > shaders . sky_shader . version_is_valid ( version ) ) ;
ubo_size = gen_code . uniform_total_size ;
ubo_offsets = gen_code . uniform_offsets ;
texture_uniforms = gen_code . texture_uniforms ;
valid = true ;
}
bool SkyShaderData : : is_animated ( ) const {
return false ;
}
bool SkyShaderData : : casts_shadows ( ) const {
return false ;
}
RS : : ShaderNativeSourceCode SkyShaderData : : get_native_source_code ( ) const {
return MaterialStorage : : get_singleton ( ) - > shaders . sky_shader . version_get_native_source_code ( version ) ;
}
SkyShaderData : : SkyShaderData ( ) {
valid = false ;
}
SkyShaderData : : ~ SkyShaderData ( ) {
if ( version . is_valid ( ) ) {
MaterialStorage : : get_singleton ( ) - > shaders . sky_shader . version_free ( version ) ;
}
}
GLES3 : : ShaderData * GLES3 : : _create_sky_shader_func ( ) {
SkyShaderData * shader_data = memnew ( SkyShaderData ) ;
return shader_data ;
}
////////////////////////////////////////////////////////////////////////////////
// Sky material
2022-05-13 15:04:37 +02:00
void SkyMaterialData : : update_parameters ( const HashMap < StringName , Variant > & p_parameters , bool p_uniform_dirty , bool p_textures_dirty ) {
2022-05-16 20:56:03 +02:00
uniform_set_updated = true ;
2023-06-13 22:20:11 +02:00
update_parameters_internal ( p_parameters , p_uniform_dirty , p_textures_dirty , shader_data - > uniforms , shader_data - > ubo_offsets . ptr ( ) , shader_data - > texture_uniforms , shader_data - > default_texture_params , shader_data - > ubo_size , true ) ;
2022-04-30 00:34:01 +02:00
}
SkyMaterialData : : ~ SkyMaterialData ( ) {
}
GLES3 : : MaterialData * GLES3 : : _create_sky_material_func ( ShaderData * p_shader ) {
SkyMaterialData * material_data = memnew ( SkyMaterialData ) ;
material_data - > shader_data = static_cast < SkyShaderData * > ( p_shader ) ;
//update will happen later anyway so do nothing.
return material_data ;
}
void SkyMaterialData : : bind_uniforms ( ) {
// Bind Material Uniforms
2022-05-10 19:02:44 +02:00
glBindBufferBase ( GL_UNIFORM_BUFFER , SKY_MATERIAL_UNIFORM_LOCATION , uniform_buffer ) ;
2022-05-03 22:28:15 +02:00
2023-03-25 10:46:33 +01:00
bind_uniforms_generic ( texture_cache , shader_data - > texture_uniforms ) ;
2022-05-03 22:28:15 +02:00
}
////////////////////////////////////////////////////////////////////////////////
// Scene SHADER
void SceneShaderData : : set_code ( const String & p_code ) {
2023-11-11 15:13:23 +01:00
// Initialize and compile the shader.
2022-05-03 22:28:15 +02:00
code = p_code ;
valid = false ;
ubo_size = 0 ;
uniforms . clear ( ) ;
uses_point_size = false ;
uses_alpha = false ;
uses_alpha_clip = false ;
uses_blend_alpha = false ;
2023-01-03 18:26:15 +01:00
uses_depth_prepass_alpha = false ;
2022-05-03 22:28:15 +02:00
uses_discard = false ;
uses_roughness = false ;
uses_normal = false ;
2023-11-11 15:13:23 +01:00
uses_particle_trails = false ;
2022-05-03 22:28:15 +02:00
wireframe = false ;
unshaded = false ;
uses_vertex = false ;
uses_position = false ;
uses_sss = false ;
uses_transmittance = false ;
uses_screen_texture = false ;
2023-11-11 15:13:23 +01:00
uses_screen_texture_mipmaps = false ;
2022-05-03 22:28:15 +02:00
uses_depth_texture = false ;
uses_normal_texture = false ;
uses_time = false ;
2023-11-11 15:13:23 +01:00
uses_vertex_time = false ;
uses_fragment_time = false ;
2022-05-03 22:28:15 +02:00
writes_modelview_or_projection = false ;
uses_world_coordinates = false ;
2023-11-11 15:13:23 +01:00
uses_tangent = false ;
uses_color = false ;
uses_uv = false ;
uses_uv2 = false ;
uses_custom0 = false ;
uses_custom1 = false ;
uses_custom2 = false ;
uses_custom3 = false ;
uses_bones = false ;
uses_weights = false ;
if ( code . is_empty ( ) ) {
return ; // Just invalid, but no error.
}
ShaderCompiler : : GeneratedCode gen_code ;
// Actual enums set further down after compilation.
int blend_modei = BLEND_MODE_MIX ;
int depth_testi = DEPTH_TEST_ENABLED ;
int alpha_antialiasing_modei = ALPHA_ANTIALIASING_OFF ;
int cull_modei = CULL_BACK ;
int depth_drawi = DEPTH_DRAW_OPAQUE ;
2022-05-03 22:28:15 +02:00
ShaderCompiler : : IdentifierActions actions ;
actions . entry_point_stages [ " vertex " ] = ShaderCompiler : : STAGE_VERTEX ;
actions . entry_point_stages [ " fragment " ] = ShaderCompiler : : STAGE_FRAGMENT ;
actions . entry_point_stages [ " light " ] = ShaderCompiler : : STAGE_FRAGMENT ;
actions . render_mode_values [ " blend_add " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_ADD ) ;
actions . render_mode_values [ " blend_mix " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_MIX ) ;
actions . render_mode_values [ " blend_sub " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_SUB ) ;
actions . render_mode_values [ " blend_mul " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_MUL ) ;
2024-05-01 11:12:31 +02:00
actions . render_mode_values [ " blend_premul_alpha " ] = Pair < int * , int > ( & blend_modei , BLEND_MODE_PREMULT_ALPHA ) ;
2022-05-03 22:28:15 +02:00
actions . render_mode_values [ " alpha_to_coverage " ] = Pair < int * , int > ( & alpha_antialiasing_modei , ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE ) ;
actions . render_mode_values [ " alpha_to_coverage_and_one " ] = Pair < int * , int > ( & alpha_antialiasing_modei , ALPHA_ANTIALIASING_ALPHA_TO_COVERAGE_AND_TO_ONE ) ;
actions . render_mode_values [ " depth_draw_never " ] = Pair < int * , int > ( & depth_drawi , DEPTH_DRAW_DISABLED ) ;
actions . render_mode_values [ " depth_draw_opaque " ] = Pair < int * , int > ( & depth_drawi , DEPTH_DRAW_OPAQUE ) ;
actions . render_mode_values [ " depth_draw_always " ] = Pair < int * , int > ( & depth_drawi , DEPTH_DRAW_ALWAYS ) ;
actions . render_mode_values [ " depth_test_disabled " ] = Pair < int * , int > ( & depth_testi , DEPTH_TEST_DISABLED ) ;
actions . render_mode_values [ " cull_disabled " ] = Pair < int * , int > ( & cull_modei , CULL_DISABLED ) ;
actions . render_mode_values [ " cull_front " ] = Pair < int * , int > ( & cull_modei , CULL_FRONT ) ;
actions . render_mode_values [ " cull_back " ] = Pair < int * , int > ( & cull_modei , CULL_BACK ) ;
actions . render_mode_flags [ " unshaded " ] = & unshaded ;
actions . render_mode_flags [ " wireframe " ] = & wireframe ;
actions . render_mode_flags [ " particle_trails " ] = & uses_particle_trails ;
2023-10-06 03:11:48 +02:00
actions . render_mode_flags [ " world_vertex_coords " ] = & uses_world_coordinates ;
2022-05-03 22:28:15 +02:00
actions . usage_flag_pointers [ " ALPHA " ] = & uses_alpha ;
actions . usage_flag_pointers [ " ALPHA_SCISSOR_THRESHOLD " ] = & uses_alpha_clip ;
2022-06-10 11:09:17 +02:00
// Use alpha clip pipeline for alpha hash/dither.
// This prevents sorting issues inherent to alpha blending and allows such materials to cast shadows.
actions . usage_flag_pointers [ " ALPHA_HASH_SCALE " ] = & uses_alpha_clip ;
2023-01-03 18:26:15 +01:00
actions . render_mode_flags [ " depth_prepass_alpha " ] = & uses_depth_prepass_alpha ;
2022-05-03 22:28:15 +02:00
actions . usage_flag_pointers [ " SSS_STRENGTH " ] = & uses_sss ;
actions . usage_flag_pointers [ " SSS_TRANSMITTANCE_DEPTH " ] = & uses_transmittance ;
actions . usage_flag_pointers [ " DISCARD " ] = & uses_discard ;
actions . usage_flag_pointers [ " TIME " ] = & uses_time ;
actions . usage_flag_pointers [ " ROUGHNESS " ] = & uses_roughness ;
actions . usage_flag_pointers [ " NORMAL " ] = & uses_normal ;
actions . usage_flag_pointers [ " NORMAL_MAP " ] = & uses_normal ;
actions . usage_flag_pointers [ " POINT_SIZE " ] = & uses_point_size ;
actions . usage_flag_pointers [ " POINT_COORD " ] = & uses_point_size ;
actions . write_flag_pointers [ " MODELVIEW_MATRIX " ] = & writes_modelview_or_projection ;
actions . write_flag_pointers [ " PROJECTION_MATRIX " ] = & writes_modelview_or_projection ;
actions . write_flag_pointers [ " VERTEX " ] = & uses_vertex ;
actions . write_flag_pointers [ " POSITION " ] = & uses_position ;
2022-05-10 19:02:44 +02:00
actions . usage_flag_pointers [ " TANGENT " ] = & uses_tangent ;
actions . usage_flag_pointers [ " BINORMAL " ] = & uses_tangent ;
2023-10-31 15:51:07 +01:00
actions . usage_flag_pointers [ " ANISOTROPY " ] = & uses_tangent ;
actions . usage_flag_pointers [ " ANISOTROPY_FLOW " ] = & uses_tangent ;
2022-05-10 19:02:44 +02:00
actions . usage_flag_pointers [ " COLOR " ] = & uses_color ;
actions . usage_flag_pointers [ " UV " ] = & uses_uv ;
actions . usage_flag_pointers [ " UV2 " ] = & uses_uv2 ;
actions . usage_flag_pointers [ " CUSTOM0 " ] = & uses_custom0 ;
actions . usage_flag_pointers [ " CUSTOM1 " ] = & uses_custom1 ;
actions . usage_flag_pointers [ " CUSTOM2 " ] = & uses_custom2 ;
actions . usage_flag_pointers [ " CUSTOM3 " ] = & uses_custom3 ;
actions . usage_flag_pointers [ " BONE_INDICES " ] = & uses_bones ;
actions . usage_flag_pointers [ " BONE_WEIGHTS " ] = & uses_weights ;
2022-05-03 22:28:15 +02:00
actions . uniforms = & uniforms ;
Error err = MaterialStorage : : get_singleton ( ) - > shaders . compiler_scene . compile ( RS : : SHADER_SPATIAL , code , & actions , path , gen_code ) ;
ERR_FAIL_COND_MSG ( err ! = OK , " Shader compilation failed. " ) ;
if ( version . is_null ( ) ) {
version = MaterialStorage : : get_singleton ( ) - > shaders . scene_shader . version_create ( ) ;
}
2023-11-11 15:13:23 +01:00
blend_mode = BlendMode ( blend_modei ) ;
alpha_antialiasing_mode = AlphaAntiAliasing ( alpha_antialiasing_modei ) ;
2022-05-03 22:28:15 +02:00
depth_draw = DepthDraw ( depth_drawi ) ;
depth_test = DepthTest ( depth_testi ) ;
cull_mode = Cull ( cull_modei ) ;
2023-11-11 15:13:23 +01:00
2023-11-19 16:32:55 +01:00
vertex_input_mask = RS : : ARRAY_FORMAT_VERTEX | RS : : ARRAY_FORMAT_NORMAL ; // We can always read vertices and normals.
vertex_input_mask | = uses_tangent < < RS : : ARRAY_TANGENT ;
vertex_input_mask | = uses_color < < RS : : ARRAY_COLOR ;
vertex_input_mask | = uses_uv < < RS : : ARRAY_TEX_UV ;
vertex_input_mask | = uses_uv2 < < RS : : ARRAY_TEX_UV2 ;
vertex_input_mask | = uses_custom0 < < RS : : ARRAY_CUSTOM0 ;
vertex_input_mask | = uses_custom1 < < RS : : ARRAY_CUSTOM1 ;
vertex_input_mask | = uses_custom2 < < RS : : ARRAY_CUSTOM2 ;
vertex_input_mask | = uses_custom3 < < RS : : ARRAY_CUSTOM3 ;
vertex_input_mask | = uses_bones < < RS : : ARRAY_BONES ;
vertex_input_mask | = uses_weights < < RS : : ARRAY_WEIGHTS ;
2023-11-11 15:13:23 +01:00
2023-01-05 20:55:59 +01:00
uses_screen_texture = gen_code . uses_screen_texture ;
2023-11-11 15:13:23 +01:00
uses_screen_texture_mipmaps = gen_code . uses_screen_texture_mipmaps ;
2023-01-05 20:55:59 +01:00
uses_depth_texture = gen_code . uses_depth_texture ;
uses_normal_texture = gen_code . uses_normal_roughness_texture ;
2022-11-13 21:46:52 +01:00
uses_vertex_time = gen_code . uses_vertex_time ;
uses_fragment_time = gen_code . uses_fragment_time ;
2022-05-03 22:28:15 +02:00
2023-02-26 01:24:41 +01:00
# ifdef DEBUG_ENABLED
if ( uses_particle_trails ) {
WARN_PRINT_ONCE_ED ( " Particle trails are only available when using the Forward+ or Mobile rendering backends. " ) ;
}
if ( uses_sss ) {
WARN_PRINT_ONCE_ED ( " Sub-surface scattering is only available when using the Forward+ rendering backend. " ) ;
}
if ( uses_transmittance ) {
WARN_PRINT_ONCE_ED ( " Transmittance is only available when using the Forward+ rendering backend. " ) ;
}
if ( uses_normal_texture ) {
WARN_PRINT_ONCE_ED ( " Reading from the normal-roughness texture is only available when using the Forward+ or Mobile rendering backends. " ) ;
}
# endif
2022-05-03 22:28:15 +02:00
#if 0
print_line ( " **compiling shader: " ) ;
print_line ( " **defines: \n " ) ;
for ( int i = 0 ; i < gen_code . defines . size ( ) ; i + + ) {
print_line ( gen_code . defines [ i ] ) ;
}
2022-08-09 18:29:49 +02:00
HashMap < String , String > : : Iterator el = gen_code . code . begin ( ) ;
2022-05-03 22:28:15 +02:00
while ( el ) {
2022-08-09 18:29:49 +02:00
print_line ( " \n **code " + el - > key + " : \n " + el - > value ) ;
+ + el ;
2022-05-03 22:28:15 +02:00
}
print_line ( " \n **uniforms: \n " + gen_code . uniforms ) ;
print_line ( " \n **vertex_globals: \n " + gen_code . stage_globals [ ShaderCompiler : : STAGE_VERTEX ] ) ;
print_line ( " \n **fragment_globals: \n " + gen_code . stage_globals [ ShaderCompiler : : STAGE_FRAGMENT ] ) ;
# endif
2023-03-25 10:46:33 +01:00
LocalVector < ShaderGLES3 : : TextureUniformData > texture_uniform_data = get_texture_uniform_data ( gen_code . texture_uniforms ) ;
2022-05-03 22:28:15 +02:00
2023-03-25 10:46:33 +01:00
MaterialStorage : : get_singleton ( ) - > shaders . scene_shader . version_set_code ( version , gen_code . code , gen_code . uniforms , gen_code . stage_globals [ ShaderCompiler : : STAGE_VERTEX ] , gen_code . stage_globals [ ShaderCompiler : : STAGE_FRAGMENT ] , gen_code . defines , texture_uniform_data ) ;
2022-05-03 22:28:15 +02:00
ERR_FAIL_COND ( ! MaterialStorage : : get_singleton ( ) - > shaders . scene_shader . version_is_valid ( version ) ) ;
ubo_size = gen_code . uniform_total_size ;
ubo_offsets = gen_code . uniform_offsets ;
texture_uniforms = gen_code . texture_uniforms ;
2023-11-11 15:13:23 +01:00
// If any form of Alpha Antialiasing is enabled, set the blend mode to alpha to coverage.
2022-05-03 22:28:15 +02:00
if ( alpha_antialiasing_mode ! = ALPHA_ANTIALIASING_OFF ) {
blend_mode = BLEND_MODE_ALPHA_TO_COVERAGE ;
}
2023-05-23 22:17:45 +02:00
if ( blend_mode = = BLEND_MODE_ADD | | blend_mode = = BLEND_MODE_SUB | | blend_mode = = BLEND_MODE_MUL ) {
uses_blend_alpha = true ; // Force alpha used because of blend.
}
2022-05-03 22:28:15 +02:00
valid = true ;
}
bool SceneShaderData : : is_animated ( ) const {
2022-11-13 21:46:52 +01:00
return ( uses_fragment_time & & uses_discard ) | | ( uses_vertex_time & & uses_vertex ) ;
2022-05-03 22:28:15 +02:00
}
bool SceneShaderData : : casts_shadows ( ) const {
2022-11-13 21:46:52 +01:00
bool has_read_screen_alpha = uses_screen_texture | | uses_depth_texture | | uses_normal_texture ;
bool has_base_alpha = ( uses_alpha & & ! uses_alpha_clip ) | | has_read_screen_alpha ;
bool has_alpha = has_base_alpha | | uses_blend_alpha ;
2023-01-03 18:26:15 +01:00
return ! has_alpha | | ( uses_depth_prepass_alpha & & ! ( depth_draw = = DEPTH_DRAW_DISABLED | | depth_test = = DEPTH_TEST_DISABLED ) ) ;
2022-05-03 22:28:15 +02:00
}
RS : : ShaderNativeSourceCode SceneShaderData : : get_native_source_code ( ) const {
return MaterialStorage : : get_singleton ( ) - > shaders . scene_shader . version_get_native_source_code ( version ) ;
}
SceneShaderData : : SceneShaderData ( ) {
valid = false ;
uses_screen_texture = false ;
}
SceneShaderData : : ~ SceneShaderData ( ) {
if ( version . is_valid ( ) ) {
MaterialStorage : : get_singleton ( ) - > shaders . scene_shader . version_free ( version ) ;
}
}
GLES3 : : ShaderData * GLES3 : : _create_scene_shader_func ( ) {
SceneShaderData * shader_data = memnew ( SceneShaderData ) ;
return shader_data ;
}
void SceneMaterialData : : set_render_priority ( int p_priority ) {
priority = p_priority - RS : : MATERIAL_RENDER_PRIORITY_MIN ; //8 bits
}
void SceneMaterialData : : set_next_pass ( RID p_pass ) {
next_pass = p_pass ;
}
2022-05-13 15:04:37 +02:00
void SceneMaterialData : : update_parameters ( const HashMap < StringName , Variant > & p_parameters , bool p_uniform_dirty , bool p_textures_dirty ) {
2023-06-13 22:20:11 +02:00
update_parameters_internal ( p_parameters , p_uniform_dirty , p_textures_dirty , shader_data - > uniforms , shader_data - > ubo_offsets . ptr ( ) , shader_data - > texture_uniforms , shader_data - > default_texture_params , shader_data - > ubo_size , true ) ;
2022-05-03 22:28:15 +02:00
}
SceneMaterialData : : ~ SceneMaterialData ( ) {
}
GLES3 : : MaterialData * GLES3 : : _create_scene_material_func ( ShaderData * p_shader ) {
SceneMaterialData * material_data = memnew ( SceneMaterialData ) ;
material_data - > shader_data = static_cast < SceneShaderData * > ( p_shader ) ;
//update will happen later anyway so do nothing.
return material_data ;
}
void SceneMaterialData : : bind_uniforms ( ) {
// Bind Material Uniforms
2022-05-10 19:02:44 +02:00
glBindBufferBase ( GL_UNIFORM_BUFFER , SCENE_MATERIAL_UNIFORM_LOCATION , uniform_buffer ) ;
2022-04-30 00:34:01 +02:00
2023-03-25 10:46:33 +01:00
bind_uniforms_generic ( texture_cache , shader_data - > texture_uniforms ) ;
2022-04-30 00:34:01 +02:00
}
2022-11-08 07:40:03 +01:00
/* Particles SHADER */
void ParticlesShaderData : : set_code ( const String & p_code ) {
2023-11-11 15:13:23 +01:00
// Initialize and compile the shader.
2022-11-08 07:40:03 +01:00
code = p_code ;
valid = false ;
ubo_size = 0 ;
uniforms . clear ( ) ;
2023-11-11 15:13:23 +01:00
2022-11-08 07:40:03 +01:00
uses_collision = false ;
2023-11-11 15:13:23 +01:00
uses_time = false ;
2022-11-08 07:40:03 +01:00
if ( code . is_empty ( ) ) {
2023-11-11 15:13:23 +01:00
return ; // Just invalid, but no error.
2022-11-08 07:40:03 +01:00
}
ShaderCompiler : : GeneratedCode gen_code ;
2023-11-11 15:13:23 +01:00
2022-11-08 07:40:03 +01:00
ShaderCompiler : : IdentifierActions actions ;
actions . entry_point_stages [ " start " ] = ShaderCompiler : : STAGE_VERTEX ;
actions . entry_point_stages [ " process " ] = ShaderCompiler : : STAGE_VERTEX ;
actions . usage_flag_pointers [ " COLLIDED " ] = & uses_collision ;
userdata_count = 0 ;
for ( uint32_t i = 0 ; i < PARTICLES_MAX_USERDATAS ; i + + ) {
userdatas_used [ i ] = false ;
actions . usage_flag_pointers [ " USERDATA " + itos ( i + 1 ) ] = & userdatas_used [ i ] ;
}
actions . uniforms = & uniforms ;
Error err = MaterialStorage : : get_singleton ( ) - > shaders . compiler_particles . compile ( RS : : SHADER_PARTICLES , code , & actions , path , gen_code ) ;
ERR_FAIL_COND_MSG ( err ! = OK , " Shader compilation failed. " ) ;
if ( version . is_null ( ) ) {
version = MaterialStorage : : get_singleton ( ) - > shaders . particles_process_shader . version_create ( ) ;
}
for ( uint32_t i = 0 ; i < PARTICLES_MAX_USERDATAS ; i + + ) {
if ( userdatas_used [ i ] ) {
userdata_count + + ;
}
}
2023-03-25 10:46:33 +01:00
LocalVector < ShaderGLES3 : : TextureUniformData > texture_uniform_data = get_texture_uniform_data ( gen_code . texture_uniforms ) ;
2022-11-08 07:40:03 +01:00
2023-03-25 10:46:33 +01:00
MaterialStorage : : get_singleton ( ) - > shaders . particles_process_shader . version_set_code ( version , gen_code . code , gen_code . uniforms , gen_code . stage_globals [ ShaderCompiler : : STAGE_VERTEX ] , gen_code . stage_globals [ ShaderCompiler : : STAGE_FRAGMENT ] , gen_code . defines , texture_uniform_data ) ;
2022-11-08 07:40:03 +01:00
ERR_FAIL_COND ( ! MaterialStorage : : get_singleton ( ) - > shaders . particles_process_shader . version_is_valid ( version ) ) ;
ubo_size = gen_code . uniform_total_size ;
ubo_offsets = gen_code . uniform_offsets ;
texture_uniforms = gen_code . texture_uniforms ;
valid = true ;
}
bool ParticlesShaderData : : is_animated ( ) const {
return false ;
}
bool ParticlesShaderData : : casts_shadows ( ) const {
return false ;
}
RS : : ShaderNativeSourceCode ParticlesShaderData : : get_native_source_code ( ) const {
return MaterialStorage : : get_singleton ( ) - > shaders . particles_process_shader . version_get_native_source_code ( version ) ;
}
ParticlesShaderData : : ~ ParticlesShaderData ( ) {
if ( version . is_valid ( ) ) {
MaterialStorage : : get_singleton ( ) - > shaders . particles_process_shader . version_free ( version ) ;
}
}
GLES3 : : ShaderData * GLES3 : : _create_particles_shader_func ( ) {
ParticlesShaderData * shader_data = memnew ( ParticlesShaderData ) ;
return shader_data ;
}
void ParticleProcessMaterialData : : update_parameters ( const HashMap < StringName , Variant > & p_parameters , bool p_uniform_dirty , bool p_textures_dirty ) {
2023-06-13 22:20:11 +02:00
update_parameters_internal ( p_parameters , p_uniform_dirty , p_textures_dirty , shader_data - > uniforms , shader_data - > ubo_offsets . ptr ( ) , shader_data - > texture_uniforms , shader_data - > default_texture_params , shader_data - > ubo_size , true ) ;
2022-11-08 07:40:03 +01:00
}
ParticleProcessMaterialData : : ~ ParticleProcessMaterialData ( ) {
}
GLES3 : : MaterialData * GLES3 : : _create_particles_material_func ( ShaderData * p_shader ) {
ParticleProcessMaterialData * material_data = memnew ( ParticleProcessMaterialData ) ;
material_data - > shader_data = static_cast < ParticlesShaderData * > ( p_shader ) ;
//update will happen later anyway so do nothing.
return material_data ;
}
void ParticleProcessMaterialData : : bind_uniforms ( ) {
// Bind Material Uniforms
glBindBufferBase ( GL_UNIFORM_BUFFER , GLES3 : : PARTICLES_MATERIAL_UNIFORM_LOCATION , uniform_buffer ) ;
2023-03-25 10:46:33 +01:00
bind_uniforms_generic ( texture_cache , shader_data - > texture_uniforms , 1 ) ; // Start at GL_TEXTURE1 because texture slot 0 is reserved for the heightmap texture.
2022-11-08 07:40:03 +01:00
}
2022-03-21 12:25:25 +01:00
# endif // !GLES3_ENABLED