Skip to content

Instantly share code, notes, and snippets.

@michaliskambi
Created June 29, 2024 22:42
Show Gist options
  • Save michaliskambi/1bc0fb39fe91021e0d47d513a04016cf to your computer and use it in GitHub Desktop.
Save michaliskambi/1bc0fb39fe91021e0d47d513a04016cf to your computer and use it in GitHub Desktop.
Add a shader effect that sets effective texture alpha from grayscale derived from texture RGB colors
void PLUG_texture_color(
inout vec4 texture_color,
const in sampler2D texture,
const in vec4 tex_coord)
{
texture_color.a = (
texture_color.r * 0.2126 +
texture_color.g * 0.7152 +
texture_color.b * 0.0722
);
}
{ Main view, where most of the application logic takes place.
Feel free to use this code as a starting point for your own projects.
This template code is in public domain, unlike most other CGE code which
is covered by BSD or LGPL (see https://castle-engine.io/license). }
unit GameViewMain;
interface
uses Classes,
CastleVectors, CastleComponentSerialize,
CastleUIControls, CastleControls, CastleKeysMouse,
CastleScene, X3DNodes, CastleRenderOptions;
type
{ Main view, where most of the application logic takes place. }
TViewMain = class(TCastleView)
published
{ Components designed using CGE editor.
These fields will be automatically initialized at Start. }
LabelFps: TCastleLabel;
Scene1: TCastleScene;
private
procedure AddTextureEffectAlphaFromGrayscale(Node: TX3DNode);
public
constructor Create(AOwner: TComponent); override;
procedure Start; override;
procedure Update(const SecondsPassed: Single; var HandleInput: Boolean); override;
function Press(const Event: TInputPressRelease): Boolean; override;
end;
var
ViewMain: TViewMain;
implementation
uses SysUtils;
{ TViewMain ----------------------------------------------------------------- }
constructor TViewMain.Create(AOwner: TComponent);
begin
inherited;
DesignUrl := 'castle-data:/gameviewmain.castle-user-interface';
end;
procedure TViewMain.AddTextureEffectAlphaFromGrayscale(Node: TX3DNode);
var
TextureNode: TAbstractSingleTextureNode;
Effect: TEffectNode;
EffectPart: TEffectPartNode;
begin
// can be safely cast, as we enumerate only TAbstractSingleTextureNode
TextureNode := Node as TAbstractSingleTextureNode;
Effect := TEffectNode.Create;
Effect.Language := slGLSL;
{ Add TEffectPartNode which actually contains shader code.
You can load shader code from file,
you could also set it explicitly from string using EffectPart.Contents := '...'; }
EffectPart := TEffectPartNode.Create;
EffectPart.ShaderType := stFragment;
EffectPart.SetUrl(['castle-data:/effect_alpha_from_grayscale.fs']);
Effect.SetParts([EffectPart]);
{ This applies the effect to the specific texture,
which allows PLUG_texture_color to be available
( see https://castle-engine.io/compositing_shaders_doc/html/section.fragment_plugs.html ).
And we use PLUG_texture_color in effect_alpha_from_grayscale.fs,
to change the effective alpha channel of the texture. }
TextureNode.SetEffects([Effect]);
end;
procedure TViewMain.Start;
{ Add a shader effect that sets effective texture alpha
from grayscale derived from texture RGB colors. }
procedure SceneEffectAlphaFromGrayscale(const Scene: TCastleScene);
var
SavedAnimation: String;
begin
if Scene.RootNode <> nil then
begin
SavedAnimation := Scene.AutoAnimation;
Scene.RootNode.EnumerateNodes(TAbstractSingleTextureNode,
{$ifdef FPC}@{$endif} AddTextureEffectAlphaFromGrayscale, false);
{ Adding node to Scene turns off animation set by AutoAnimation, run it again.
The need to do this may disappear in future CGE versions. }
Scene.PlayAnimation(SavedAnimation, true);
end;
end;
begin
inherited;
SceneEffectAlphaFromGrayscale(Scene1);
end;
procedure TViewMain.Update(const SecondsPassed: Single; var HandleInput: Boolean);
begin
inherited;
{ This virtual method is executed every frame (many times per second). }
Assert(LabelFps <> nil, 'If you remove LabelFps from the design, remember to remove also the assignment "LabelFps.Caption := ..." from code');
LabelFps.Caption := 'FPS: ' + Container.Fps.ToString;
end;
function TViewMain.Press(const Event: TInputPressRelease): Boolean;
begin
Result := inherited;
if Result then Exit; // allow the ancestor to handle keys
{ This virtual method is executed when user presses
a key, a mouse button, or touches a touch-screen.
Note that each UI control has also events like OnPress and OnClick.
These events can be used to handle the "press", if it should do something
specific when used in that UI control.
The TViewMain.Press method should be used to handle keys
not handled in children controls.
}
// Use this to handle keys:
{
if Event.IsKey(keyXxx) then
begin
// DoSomething;
Exit(true); // key was handled
end;
}
end;
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment