Skip to content

Add Wind into the New Renderer#1033

Draft
3-X wants to merge 2 commits into117HD:masterfrom
3-X:Windy
Draft

Add Wind into the New Renderer#1033
3-X wants to merge 2 commits into117HD:masterfrom
3-X:Windy

Conversation

@3-X
Copy link
Copy Markdown

@3-X 3-X commented Mar 31, 2026

Adds wind back into the plugin by adding support for the new renderer

wind.2.mp4

@3-X
Copy link
Copy Markdown
Author

3-X commented Mar 31, 2026

Just as a note with this implementation since the zone renderer's vertex shader currently has no access to model height or model local positions, exact prior behavior matching is not possible unfortunately. Plan to explore other implementation options

@RuffledPlume
Copy link
Copy Markdown
Contributor

Just as a note with this implementation since the zone renderer's vertex shader currently has no access to model height or model local positions, exact prior behavior matching is not possible unfortunately. Plan to explore other implementation options

I have a branch which needs the dust blowing off which would provide this, essentially it adds support for SSBOs which allow individual models both static and dynamic to access unique model data. I'll be getting around to that once the latest update is out and stable.

@RuffledPlume
Copy link
Copy Markdown
Contributor

In the meantime though, we could get around the snapping by sampling the tile height instead.
LegacyRenderer has initializeTileHeightMap if that was instead pulled into HdPlugin so both renderers could use it, you'd be able to sample the 4 corners of the tile and then get the exact height of the tile at the vertex x/z.

That would allow the heightBlending to be applied again, so the grass blades at the tile plane are fixed into position.

@RuffledPlume
Copy link
Copy Markdown
Contributor

Courtesy of @Jin-Jiyunsun, without the height blending the grass sliding around it very noticeable in areas with strong wind:

java_BwDbTiFdu5.mp4

@Jin-Jiyunsun
Copy link
Copy Markdown
Contributor

Also the legacy renderer is broken by this PR:

20:57:22.059 [Client    ] WARN  r.h.o.shader.ShaderProgram     - Legacy has missing or unused UniformTexture: textureFaces
20:57:22.076 [Client    ] ERROR rs117.hd.HdPlugin              - Error while starting 117 HD
rs117.hd.opengl.shader.ShaderException: Error when compiling shader: comp.glsl
uniforms/global.glsl line 57 - error C1038: declaration of "windDirectionX" conflicts with previous declaration at 1(15)
uniforms/global.glsl line 58 - error C1038: declaration of "windDirectionZ" conflicts with previous declaration at 1(16)
uniforms/global.glsl line 59 - error C1038: declaration of "windStrength" conflicts with previous declaration at 1(17)
uniforms/global.glsl line 60 - error C1038: declaration of "windCeiling" conflicts with previous declaration at 1(18)
uniforms/global.glsl line 61 - error C1038: declaration of "windOffset" conflicts with previous declaration at 1(19)
	at rs117.hd.opengl.shader.ShaderException.compileError(ShaderException.java:83)
	at rs117.hd.opengl.shader.ShaderTemplate.compile(ShaderTemplate.java:83)
	at rs117.hd.opengl.shader.ShaderProgram.compile(ShaderProgram.java:42)
	at rs117.hd.opengl.shader.ModelSortingComputeProgram.compile(ModelSortingComputeProgram.java:26)
	at rs117.hd.renderer.legacy.LegacyRenderer.initializeShaders(LegacyRenderer.java:299)
	at rs117.hd.HdPlugin.initializeShaders(HdPlugin.java:953)
	at rs117.hd.HdPlugin.lambda$startUp$2(HdPlugin.java:687)
	at net.runelite.client.callback.ClientThread.invokeList(ClientThread.java:119)
	at net.runelite.client.callback.ClientThread.invoke(ClientThread.java:101)
	at net.runelite.client.callback.Hooks.tick(Hooks.java:241)
	at client.io(client.java:17007)
	at client.il(client.java)
	at sw.agt(sw.java:447)
	at sw.ko(sw.java)
	at sw.run(sw.java:17786)
	at java.base/java.lang.Thread.run(Thread.java:840)
20:57:22.076 [Client    ] DEBUG rs117.hd.utils.FileWatcher     - Shutting down FileWatcher
20:57:22.078 [Client    ] DEBUG r.hd.utils.jobs.JobSystem      - All workers shutdown successfully
20:57:22.078 [Client    ] DEBUG n.r.c.input.KeyManager         - Unregistered key listener: rs117.hd.utils.DeveloperTools@20307c9b
20:57:22.316 [Client    ] DEBUG injected-client                - Game state changed: LOADING (state: 25, 2 step: false)
20:57:22.316 [Client    ] DEBUG c.a.w.dps.DpsDataFetcher       - WS player name changed prev=[jiyunsun] next=[null]
20:57:22.316 [AWT-EventQueue-0] DEBUG n.r.c.config.ConfigManager     - Setting configuration value for runelite.hdplugin to false
20:57:22.316 [AWT-EventQueue-0] DEBUG n.r.c.p.PluginManager          - Plugin HdPlugin is now stopped
20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.GameTick - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onGameTick(net.runelite.api.events.GameTick), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4191/0x000002f01cb10230@40eb77b4)
20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.BeforeRender - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onBeforeRender(net.runelite.api.events.BeforeRender), priority=-1.0, lambda=rs117.hd.HdPlugin$$Lambda$4192/0x000002f01cb10460@511e32d6)
20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.GameStateChanged - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onGameStateChanged(net.runelite.api.events.GameStateChanged), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4193/0x000002f01cb10690@7a1e0730)
20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.client.events.ConfigChanged - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onConfigChanged(net.runelite.client.events.ConfigChanged), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4194/0x000002f01cb108c0@1e8d1cee)
20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.ClientTick - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onClientTick(net.runelite.api.events.ClientTick), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4195/0x000002f01cb10af0@69dde1dd)
20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.FocusChanged - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onFocusChanged(net.runelite.api.events.FocusChanged), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4196/0x000002f01cb10d20@9f92a07)
20:57:22.320 [Client    ] DEBUG n.r.client.callback.Hooks      - Graphics reset!
20:57:22.344 [Map Loader] DEBUG n.r.c.p.r.RoofRemovalPlugin    - Roof override duration: 875.4 μs
20:57:22.346 [Map Loader] DEBUG n.r.c.p.r.RoofRemovalPlugin    - Roof building duration: 681.5 μs
20:57:22.352 [Client    ] DEBUG c.t.TilePacksPlugin            - Changing world view
20:57:22.352 [Client    ] DEBUG n.r.c.p.g.GroundMarkerPlugin   - Loading points for region 9018
20:57:22.352 [Client    ] DEBUG n.r.c.p.g.GroundMarkerPlugin   - Loading points for region 9019
20:57:22.352 [Client    ] DEBUG n.r.c.p.g.GroundMarkerPlugin   - Loading points for region 9274
20:57:22.352 [Client    ] DEBUG n.r.c.p.g.GroundMarkerPlugin   - Loading points for region 9275
20:57:22.352 [Client    ] DEBUG c.d.o.s.f.c.CourierTaskTracker - Found ledger table at LocalPoint(x=6720, y=6080, worldView=0)
20:57:22.353 [Client    ] DEBUG injected-client                - Game state changed: LOGGED_IN (state: 30, 2 step: false)
20:57:22.353 [Client    ] DEBUG c.a.w.dps.DpsDataFetcher       - WS player name changed prev=[null] next=[jiyunsun]
20:57:22.354 [Client    ] DEBUG c.h.cache.TooltipCache         - Tooltip cache was loaded in 0.5742ms.
20:57:22.356 [Client    ] DEBUG n.r.c.p.d.DiscordState         - Events: [DiscordState.EventWithTime(type=CITY_NEITIZNOT, start=2026-03-31T20:53:12.750821100Z, updated=2026-03-31T20:57:22.356415900Z), DiscordState.EventWithTime(type=IN_GAME, start=2026-03-31T20:51:04.027608Z, updated=2026-03-31T20:51:04.027608Z)]
20:57:22.356 [Client    ] DEBUG n.e.i.InstantInventoryPlugin   - Resetting features as the GameState changed to LOGGED_IN
20:57:27.837 [pool-1-thread-1] DEBUG c.a.w.WikiSyncPlugin           - ensuring active!!

@3-X
Copy link
Copy Markdown
Author

3-X commented Mar 31, 2026

Also the legacy renderer is broken by this PR:


20:57:22.059 [Client    ] WARN  r.h.o.shader.ShaderProgram     - Legacy has missing or unused UniformTexture: textureFaces

20:57:22.076 [Client    ] ERROR rs117.hd.HdPlugin              - Error while starting 117 HD

rs117.hd.opengl.shader.ShaderException: Error when compiling shader: comp.glsl

uniforms/global.glsl line 57 - error C1038: declaration of "windDirectionX" conflicts with previous declaration at 1(15)

uniforms/global.glsl line 58 - error C1038: declaration of "windDirectionZ" conflicts with previous declaration at 1(16)

uniforms/global.glsl line 59 - error C1038: declaration of "windStrength" conflicts with previous declaration at 1(17)

uniforms/global.glsl line 60 - error C1038: declaration of "windCeiling" conflicts with previous declaration at 1(18)

uniforms/global.glsl line 61 - error C1038: declaration of "windOffset" conflicts with previous declaration at 1(19)

	at rs117.hd.opengl.shader.ShaderException.compileError(ShaderException.java:83)

	at rs117.hd.opengl.shader.ShaderTemplate.compile(ShaderTemplate.java:83)

	at rs117.hd.opengl.shader.ShaderProgram.compile(ShaderProgram.java:42)

	at rs117.hd.opengl.shader.ModelSortingComputeProgram.compile(ModelSortingComputeProgram.java:26)

	at rs117.hd.renderer.legacy.LegacyRenderer.initializeShaders(LegacyRenderer.java:299)

	at rs117.hd.HdPlugin.initializeShaders(HdPlugin.java:953)

	at rs117.hd.HdPlugin.lambda$startUp$2(HdPlugin.java:687)

	at net.runelite.client.callback.ClientThread.invokeList(ClientThread.java:119)

	at net.runelite.client.callback.ClientThread.invoke(ClientThread.java:101)

	at net.runelite.client.callback.Hooks.tick(Hooks.java:241)

	at client.io(client.java:17007)

	at client.il(client.java)

	at sw.agt(sw.java:447)

	at sw.ko(sw.java)

	at sw.run(sw.java:17786)

	at java.base/java.lang.Thread.run(Thread.java:840)

20:57:22.076 [Client    ] DEBUG rs117.hd.utils.FileWatcher     - Shutting down FileWatcher

20:57:22.078 [Client    ] DEBUG r.hd.utils.jobs.JobSystem      - All workers shutdown successfully

20:57:22.078 [Client    ] DEBUG n.r.c.input.KeyManager         - Unregistered key listener: rs117.hd.utils.DeveloperTools@20307c9b

20:57:22.316 [Client    ] DEBUG injected-client                - Game state changed: LOADING (state: 25, 2 step: false)

20:57:22.316 [Client    ] DEBUG c.a.w.dps.DpsDataFetcher       - WS player name changed prev=[jiyunsun] next=[null]

20:57:22.316 [AWT-EventQueue-0] DEBUG n.r.c.config.ConfigManager     - Setting configuration value for runelite.hdplugin to false

20:57:22.316 [AWT-EventQueue-0] DEBUG n.r.c.p.PluginManager          - Plugin HdPlugin is now stopped

20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.GameTick - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onGameTick(net.runelite.api.events.GameTick), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4191/0x000002f01cb10230@40eb77b4)

20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.BeforeRender - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onBeforeRender(net.runelite.api.events.BeforeRender), priority=-1.0, lambda=rs117.hd.HdPlugin$$Lambda$4192/0x000002f01cb10460@511e32d6)

20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.GameStateChanged - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onGameStateChanged(net.runelite.api.events.GameStateChanged), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4193/0x000002f01cb10690@7a1e0730)

20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.client.events.ConfigChanged - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onConfigChanged(net.runelite.client.events.ConfigChanged), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4194/0x000002f01cb108c0@1e8d1cee)

20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.ClientTick - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onClientTick(net.runelite.api.events.ClientTick), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4195/0x000002f01cb10af0@69dde1dd)

20:57:22.317 [Client    ] DEBUG n.r.c.eventbus.EventBus        - Registering class net.runelite.api.events.FocusChanged - EventBus.Subscriber(object=rs117.hd.HdPlugin@55589ef5, method=public void rs117.hd.HdPlugin.onFocusChanged(net.runelite.api.events.FocusChanged), priority=0.0, lambda=rs117.hd.HdPlugin$$Lambda$4196/0x000002f01cb10d20@9f92a07)

20:57:22.320 [Client    ] DEBUG n.r.client.callback.Hooks      - Graphics reset!

20:57:22.344 [Map Loader] DEBUG n.r.c.p.r.RoofRemovalPlugin    - Roof override duration: 875.4 μs

20:57:22.346 [Map Loader] DEBUG n.r.c.p.r.RoofRemovalPlugin    - Roof building duration: 681.5 μs

20:57:22.352 [Client    ] DEBUG c.t.TilePacksPlugin            - Changing world view

20:57:22.352 [Client    ] DEBUG n.r.c.p.g.GroundMarkerPlugin   - Loading points for region 9018

20:57:22.352 [Client    ] DEBUG n.r.c.p.g.GroundMarkerPlugin   - Loading points for region 9019

20:57:22.352 [Client    ] DEBUG n.r.c.p.g.GroundMarkerPlugin   - Loading points for region 9274

20:57:22.352 [Client    ] DEBUG n.r.c.p.g.GroundMarkerPlugin   - Loading points for region 9275

20:57:22.352 [Client    ] DEBUG c.d.o.s.f.c.CourierTaskTracker - Found ledger table at LocalPoint(x=6720, y=6080, worldView=0)

20:57:22.353 [Client    ] DEBUG injected-client                - Game state changed: LOGGED_IN (state: 30, 2 step: false)

20:57:22.353 [Client    ] DEBUG c.a.w.dps.DpsDataFetcher       - WS player name changed prev=[null] next=[jiyunsun]

20:57:22.354 [Client    ] DEBUG c.h.cache.TooltipCache         - Tooltip cache was loaded in 0.5742ms.

20:57:22.356 [Client    ] DEBUG n.r.c.p.d.DiscordState         - Events: [DiscordState.EventWithTime(type=CITY_NEITIZNOT, start=2026-03-31T20:53:12.750821100Z, updated=2026-03-31T20:57:22.356415900Z), DiscordState.EventWithTime(type=IN_GAME, start=2026-03-31T20:51:04.027608Z, updated=2026-03-31T20:51:04.027608Z)]

20:57:22.356 [Client    ] DEBUG n.e.i.InstantInventoryPlugin   - Resetting features as the GameState changed to LOGGED_IN

20:57:27.837 [pool-1-thread-1] DEBUG c.a.w.WikiSyncPlugin           - ensuring active!!

Lmao I have a fix for this i did last night, I just forgot to push the update I guess, will push update when I get home

data in vNormal.w alongside the existing height ratio and wind reach
@3-X
Copy link
Copy Markdown
Author

3-X commented Apr 1, 2026

Very gross implementation to get a bit closer to legacy, will almost certainly not go this path but wanted to share regardless

packs the actual model origin (X, Z) into the 16-bit wind
data in vNormal.w alongside the existing height ratio and wind reach.

wind.3.mp4

@Jin-Jiyunsun
Copy link
Copy Markdown
Contributor

Jin-Jiyunsun commented Apr 1, 2026

Can you improve the granularity so that each individual object is affected by the wind? Right now they are in rather large blocks rather than each individual tile

@3-X
Copy link
Copy Markdown
Author

3-X commented Apr 1, 2026

Can you improve the granularity so that each individual object is affected by the wind? Right now they are in rather large blocks rather than each individual tile

Unfortunately with this gross implementation i am limited with the number of bits i can pass, so by increasing granularity i have to give up how tall an object is affecting how much it moves and using a standard approximation instead which doesn't look right either as seen below

wind.4.mp4

This is part of the reason why i don't think this implementation method is necessarily the path forward but figure its important to share these experiments

@Jin-Jiyunsun
Copy link
Copy Markdown
Contributor

Jin-Jiyunsun commented Apr 1, 2026

Very gross implementation to get a bit closer to legacy, will almost certainly not go this path but wanted to share regardless

packs the actual model origin (X, Z) into the 16-bit wind data in vNormal.w alongside the existing height ratio and wind reach.
wind.3.mp4

Ah ok, in that case this the one in this reply is probably good enough as a stop gap to bring it back properly, my two cents

Perhaps we could implement it this way and move it back to experimental for the time being?

@3-X
Copy link
Copy Markdown
Author

3-X commented Apr 1, 2026

Up to the group, happy either way but i would definitely suggest we move this to experimental if we do want to roll it out as you suggested

This would definitely just be a stop gap until a better method/tools come around, I don't want to shoe horn us into this implementation permanently knowing its limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants