Skip to content

Texture

Demo code
vue
<script setup lang="ts">
import { ContactShadows, Environment, OrbitControls } from '@tresjs/cientos'
import { TresCanvas, useTexture } from '@tresjs/core'
import { TresLeches, useControls } from '@tresjs/leches'
import { NoToneMapping, RepeatWrapping, SRGBColorSpace } from 'three'
import { BlendFunction, ColorChannel, ToneMappingMode } from 'postprocessing'
import { ref, watch } from 'vue'
import { EffectComposerPmndrs, TexturePmndrs, ToneMappingPmndrs } from '@tresjs/post-processing'
import type { Ref } from 'vue'
import type { EffectPass, TextureEffect } from 'postprocessing'

import '@tresjs/leches/styles'

const gl = {
  clearColor: '#ffffff',
  toneMapping: NoToneMapping,
  toneMappingExposure: 2,
}

const textureEffectRef: Ref<{ pass: EffectPass, effect: TextureEffect } | null> = ref(null)

const texture = await useTexture(['https://raw.githubusercontent.com/Tresjs/assets/main/textures/dirt/color.jpg'])
texture.colorSpace = SRGBColorSpace
texture.wrapS = texture.wrapT = RepeatWrapping

const { blendFunction, rotation, opacity } = useControls({
  blendFunction: {
    options: Object.keys(BlendFunction).map(key => ({
      text: key,
      value: BlendFunction[key as keyof typeof BlendFunction],
    })),
    value: BlendFunction.MULTIPLY,
  },
  opacity: {
    value: 1,
    min: 0,
    max: 1,
    step: 0.01,
  },
  repeat: texture.repeat,
  offset: texture.offset,
  center: texture.center,
  rotation: {
    value: texture.rotation,
    min: 0,
    max: 2 * Math.PI,
    step: 0.001,
  },
  mixColors: {
    label: 'Mix colors (RGB)',
    type: 'button',
    onClick: () => {
      textureEffectRef.value?.effect.setTextureSwizzleRGBA(
        ColorChannel.GREEN,
        ColorChannel.BLUE,
        ColorChannel.RED,
        ColorChannel.ALPHA,
      )
    },
    size: 'md',
  },
  resetColors: {
    label: 'Reset colors (RGB)',
    type: 'button',
    onClick: () => {
      textureEffectRef.value?.effect.setTextureSwizzleRGBA(
        ColorChannel.RED,
        ColorChannel.GREEN,
        ColorChannel.BLUE,
        ColorChannel.ALPHA,
      )
    },
    size: 'md',
  },
})

watch(rotation, () => {
  texture.rotation = rotation.value
})
</script>

<template>
  <div class="aspect-16/9">
    <TresCanvas
      v-bind="gl"
    >
      <TresPerspectiveCamera
        :position="[5, 7, 5]"
        :look-at="[0, 0, 0]"
      />
      <OrbitControls auto-rotate />

      <TresMesh :position="[0, .5, 0]">
        <TresBoxGeometry :args="[2, 2, 2]" />
        <TresMeshBasicMaterial color="white" />
      </TresMesh>

      <ContactShadows
        :opacity="1"
        :position-y="-.5"
      />

      <Suspense>
        <Environment background :blur="0.1" preset="dawn" />
      </Suspense>

      <Suspense>
        <EffectComposerPmndrs>
          <TexturePmndrs
            ref="textureEffectRef"
            :blendFunction="Number(blendFunction)"
            :texture="texture"
            :opacity="opacity"
          />
          <ToneMappingPmndrs :mode="ToneMappingMode.AGX" />
        </EffectComposerPmndrs>
      </Suspense>
    </TresCanvas>
  </div>
  <TresLeches :float="false" />
</template>

The TextureEffect component is part of the postprocessing package. It allows rendering a texture with customizable options to create various visual effects.

Usage

The <TexturePmndrs> component is easy to use and provides customizable options to suit different visual styles.

INFO

This component is designed to work with a provided texture and does not include built-in functionality to modify the texture itself.

If you need to adjust properties such as rotation, repeat, or other attributes, you should modify them directly the texture (See usage example below) that you pass to the <TexturePmndrs /> component.

vue
<script setup lang="ts">
import { EffectComposerPmndrs, TexturePmndrs } from '@tresjs/post-processing/pmndrs'
import { TresCanvas, useTexture } from '@tresjs/core'
import { NoToneMapping, RepeatWrapping, SRGBColorSpace } from 'three'
import { BlendFunction, ColorChannel } from 'postprocessing'

const gl = {
  toneMapping: NoToneMapping,
}

const effectProps = {
  blendFunction: BlendFunction.OVERLAY,
  opacity: 0.65
}

const texture = await useTexture(['your-path-to-texture'])
texture.colorSpace = SRGBColorSpace
texture.wrapS = texture.wrapT = RepeatWrapping
texture.rotation = Math.PI / 2
texture.repeat.set( 2, 2 );

function setTextureSwizzleRGBA(red, green, blue, alpha) {
  // This is an example of using a function belonging to the TextureEffect class.
  // https://pmndrs.github.io/postprocessing/public/docs/file/src/effects/TextureEffect.js.html#lineNumber192
  textureEffectRef.value?.effect.setTextureSwizzleRGBA(red, green, blue, alpha)
}

// Example how to mix texture's color channels.
setTextureSwizzleRGBA(ColorChannel.GREEN, ColorChannel.BLUE, ColorChannel.RED, ColorChannel.ALPHA)

// Example how to reset the texture's color channels (default).
setTextureSwizzleRGBA(ColorChannel.RED, ColorChannel.BLUE, ColorChannel.GREEN, ColorChannel.ALPHA)
</script>

<template>
  <TresCanvas v-bind="gl">
    <TresPerspectiveCamera :position="[5, 5, 5]" />

    <!-- Your Scene -->

    <Suspense>
      <EffectComposerPmndrs>
        <TexturePmndrs v-bind="effectProps" :texture="texture" />
      </EffectComposerPmndrs>
    </Suspense>
  </TresCanvas>
</template>

Props

PropDescriptionDefault
blendFunctionDefines how the effect blends with the original scene. See the BlendFunction options.BlendFunction.NORMAL
textureThe texture used for the effect. See the Texture documentationnull
opacityThe opacity of the texture.1.0

Further Reading

For more details, see the TextureEffect documentation.