Merge remote-tracking branch 'upstream/master' into fix_fb_depth24stencil8

This commit is contained in:
David Bernard 2014-11-05 12:15:38 +01:00
commit 4fdde38bc2
48 changed files with 2192 additions and 895 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
jme3-android-native/libs/stb_image/armeabi/libstbijme.so Normal file → Executable file

Binary file not shown.

BIN
jme3-android-native/libs/stb_image/mips/libstbijme.so Normal file → Executable file

Binary file not shown.

Binary file not shown.

BIN
jme3-android-native/libs/stb_image/x86/libstbijme.so Normal file → Executable file

Binary file not shown.

Binary file not shown.

View File

@ -1,9 +1,5 @@
// OpenAL Soft r1.15.1 // OpenAL Soft r1.16
//String openALSoftUrl = 'http://repo.or.cz/w/openal-soft.git/snapshot/9b6a226da55a987cb883f425eeb568776ea12c8d.zip' String openALSoftUrl = 'http://repo.or.cz/w/openal-soft.git/snapshot/e5016f814a265ed592a88acea95cf912c4bfdf12.zip'
// OpenAL Soft r1.15.1 + Android OpenSL Support
String openALSoftUrl = 'http://repo.or.cz/w/openal-soft.git/snapshot/be25e6802dacad78876c6fa1d6a5c63797b8a9ed.zip'
// OpenAL Soft r1.15.1 latest build (at the time)
//String openALSoftUrl = 'http://repo.or.cz/w/openal-soft.git/snapshot/3f5914e0949ee12b504ee7254990e007ff8057ef.zip'
String openALSoftZipFile = 'OpenALSoft.zip' String openALSoftZipFile = 'OpenALSoft.zip'
// OpenAL Soft directory the download is extracted into // OpenAL Soft directory the download is extracted into
@ -81,22 +77,23 @@ task generateOpenAlSoftHeaders(dependsOn: copyJmeOpenALSoft) << {
String classes = "" String classes = ""
.concat("com.jme3.audio.android.AndroidOpenALSoftAudioRenderer, ") .concat("com.jme3.audio.android.AndroidOpenALSoftAudioRenderer, ")
// println "openalsoft classes = " + classes // println "openalsoft classes = " + classes
// println "openalsoft destDir = " + destDir // println "openalsoft destDir = " + destDirPath
// println "openalsoft classpath = " + project.projectClassPath // println "openalsoft classpath = " + project.projectClassPath
ant.javah( exec {
classpath: project.projectClassPath, executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
destdir: destDirPath, args '-d', destDirPath
class: classes args '-classpath', project.projectClassPath
) args "com.jme3.audio.android.AndroidOpenALSoftAudioRenderer"
}
} }
task buildOpenAlSoftNativeLib(type: Exec, dependsOn: generateOpenAlSoftHeaders) { task buildOpenAlSoftNativeLib(type: Exec, dependsOn: generateOpenAlSoftHeaders) {
// println "openalsoft build dir: " + openalsoftBuildDir // println "openalsoft build dir: " + openalsoftBuildDir
// println "ndkCommandPath: " + project.ndkCommandPath // println "ndkCommandPath: " + project.ndkCommandPath
args 'TARGET_PLATFORM=android-9'
workingDir openalsoftBuildDir workingDir openalsoftBuildDir
executable rootProject.ndkCommandPath executable rootProject.ndkCommandPath
args '-j8'
} }
task updatePreCompiledOpenAlSoftLibs(type: Copy, dependsOn: buildOpenAlSoftNativeLib) { task updatePreCompiledOpenAlSoftLibs(type: Copy, dependsOn: buildOpenAlSoftNativeLib) {

View File

@ -1,58 +1,68 @@
TARGET_PLATFORM := android-9 TARGET_PLATFORM := android-9
ROOT_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
########################################################################################################
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE := openalsoftjme LOCAL_MODULE := openalsoftjme
LOCAL_ARM_MODE := arm
LOCAL_PATH := $(ROOT_PATH)
LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/include $(LOCAL_PATH)/OpenAL32/Include
LOCAL_CFLAGS := -ffast-math -DAL_BUILD_LIBRARY -DAL_ALEXT_PROTOTYPES LOCAL_C_INCLUDES += $(LOCAL_PATH) $(LOCAL_PATH)/include \
LOCAL_LDLIBS := -llog -Wl,-s $(LOCAL_PATH)/OpenAL32/Include $(LOCAL_PATH)/Alc
LOCAL_LDLIBS += -lOpenSLES
# LOCAL_CFLAGS += -DPOST_FROYO #-I$(ANDROID_NDK_ROOT)/platforms/android-9/arch-arm/usr/include/
# LOCAL_LDLIBS += -ldl -L$(ANDROID_NDK_ROOT)/platforms/android-9/arch-arm/usr/lib/
LOCAL_SRC_FILES := OpenAL32/alAuxEffectSlot.c \ LOCAL_CFLAGS := -std=c99 -ffast-math -DAL_BUILD_LIBRARY -DAL_ALEXT_PROTOTYPES
OpenAL32/alBuffer.c \ LOCAL_LDLIBS := -lOpenSLES -llog -Wl,-s
OpenAL32/alEffect.c \
OpenAL32/alError.c \ LOCAL_SRC_FILES := Alc/backends/opensl.c \
OpenAL32/alExtension.c \ Alc/backends/loopback.c \
OpenAL32/alFilter.c \ Alc/backends/wave.c \
OpenAL32/alListener.c \ Alc/backends/base.c \
OpenAL32/alSource.c \ Alc/backends/null.c \
OpenAL32/alState.c \
OpenAL32/alThunk.c \
Alc/ALc.c \ Alc/ALc.c \
Alc/ALu.c \
Alc/alcConfig.c \
Alc/alcDedicated.c \
Alc/alcEcho.c \
Alc/alcModulator.c \
Alc/alcReverb.c \
Alc/alcRing.c \
Alc/alcThread.c \
Alc/bs2b.c \
Alc/helpers.c \ Alc/helpers.c \
Alc/bs2b.c \
Alc/alcRing.c \
Alc/effects/chorus.c \
Alc/effects/flanger.c \
Alc/effects/dedicated.c \
Alc/effects/reverb.c \
Alc/effects/distortion.c \
Alc/effects/autowah.c \
Alc/effects/equalizer.c \
Alc/effects/modulator.c \
Alc/effects/echo.c \
Alc/effects/compressor.c \
Alc/effects/null.c \
Alc/alcConfig.c \
Alc/ALu.c \
Alc/mixer_c.c \
Alc/panning.c \ Alc/panning.c \
Alc/hrtf.c \ Alc/hrtf.c \
Alc/mixer.c \ Alc/mixer.c \
Alc/mixer_c.c \ Alc/midi/soft.c \
Alc/backends/loopback.c \ Alc/midi/sf2load.c \
Alc/backends/null.c \ Alc/midi/dummy.c \
Alc/backends/opensl.c \ Alc/midi/fluidsynth.c \
Alc/midi/base.c \
common/uintmap.c \
common/atomic.c \
common/threads.c \
common/rwlock.c \
OpenAL32/alBuffer.c \
OpenAL32/alPreset.c \
OpenAL32/alListener.c \
OpenAL32/alEffect.c \
OpenAL32/alExtension.c \
OpenAL32/alThunk.c \
OpenAL32/alMidi.c \
OpenAL32/alSoundfont.c \
OpenAL32/alFontsound.c \
OpenAL32/alAuxEffectSlot.c \
OpenAL32/alError.c \
OpenAL32/alFilter.c \
OpenAL32/alSource.c \
OpenAL32/alState.c \
OpenAL32/sample_cvt.c \
com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.cpp com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.cpp
# Alc/backends/alsa.c \
# Alc/backends/android.c \
# Alc/alcChorus.c \
# Alc/alcFlanger.c \
# Alc/mixer_c.c \
# Alc/backends/loopback.c \
# Alc/backends/null.c \
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View File

@ -1,3 +1,3 @@
APP_PLATFORM := android-9
APP_OPTIM := release APP_OPTIM := release
APP_ABI := all APP_ABI := all
#APP_ABI := armeabi-v7a

View File

@ -1,97 +1,89 @@
#ifndef CONFIG_H /* API declaration export attribute */
#define CONFIG_H #define AL_API __attribute__((visibility("protected")))
#define ALC_API __attribute__((visibility("protected")))
/* Define to the library version */ /* Define to the library version */
#define ALSOFT_VERSION "1.15.1" #define ALSOFT_VERSION "1.16.0"
#ifdef IN_IDE_PARSER
/* KDevelop's parser doesn't recognize the C99-standard restrict keyword, but
* recent versions (at least 4.5.1) do recognize GCC's __restrict. */
#define restrict __restrict
#endif
/* Define any available alignment declaration */
#define ALIGN(x) __attribute__((aligned(x))) #define ALIGN(x) __attribute__((aligned(x)))
/* Define if we have the Android backend */ /* Define if we have the C11 aligned_alloc function */
/* #define HAVE_ANDROID 1 */ /* #undef HAVE_ALIGNED_ALLOC */
/* Define if we have the posix_memalign function */
/* #undef HAVE_POSIX_MEMALIGN */
/* Define if we have the _aligned_malloc function */
/* #undef HAVE__ALIGNED_MALLOC */
/* Define if we have SSE CPU extensions */
/* #undef HAVE_SSE */
/* #undef HAVE_SSE2 */
/* #undef HAVE_SSE4_1 */
/* Define if we have ARM Neon CPU extensions */
/* #undef HAVE_NEON */
/* Define if we have FluidSynth support */
/* #undef HAVE_FLUIDSYNTH */
/* Define if we have the ALSA backend */ /* Define if we have the ALSA backend */
/* #define HAVE_ALSA */ /* #undef HAVE_ALSA */
/* Define if we have the OSS backend */ /* Define if we have the OSS backend */
/* #cmakedefine HAVE_OSS */ /* #undef HAVE_OSS */
/* Define if we have the Solaris backend */ /* Define if we have the Solaris backend */
/* #cmakedefine HAVE_SOLARIS */ /* #undef HAVE_SOLARIS */
/* Define if we have the SndIO backend */ /* Define if we have the SndIO backend */
/* #cmakedefine HAVE_SNDIO */ /* #undef HAVE_SNDIO */
/* Define if we have the QSA backend */
/* #undef HAVE_QSA */
/* Define if we have the MMDevApi backend */ /* Define if we have the MMDevApi backend */
/* #cmakedefine HAVE_MMDEVAPI */ /* #undef HAVE_MMDEVAPI */
/* Define if we have the DSound backend */ /* Define if we have the DSound backend */
/* #cmakedefine HAVE_DSOUND */ /* #undef HAVE_DSOUND */
/* Define if we have the Windows Multimedia backend */ /* Define if we have the Windows Multimedia backend */
/* #cmakedefine HAVE_WINMM */ /* #undef HAVE_WINMM */
/* Define if we have the PortAudio backend */ /* Define if we have the PortAudio backend */
/* #cmakedefine HAVE_PORTAUDIO */ /* #undef HAVE_PORTAUDIO */
/* Define if we have the PulseAudio backend */ /* Define if we have the PulseAudio backend */
/* #cmakedefine HAVE_PULSEAUDIO */ /* #undef HAVE_PULSEAUDIO */
/* Define if we have the CoreAudio backend */ /* Define if we have the CoreAudio backend */
/* #cmakedefine HAVE_COREAUDIO */ /* #undef HAVE_COREAUDIO */
/* Define if we have the OpenSL backend */ /* Define if we have the OpenSL backend */
#define HAVE_OPENSL /* THIS BACKEND WORKS ON >=2.3 Android!! */ #define HAVE_OPENSL
/* Define if we have the Wave Writer backend */ /* Define if we have the Wave Writer backend */
/* #cmakedefine HAVE_WAVE */ #define HAVE_WAVE
/* Define if we have dlfcn.h */
#define HAVE_DLFCN_H
/* Define if we have the stat function */ /* Define if we have the stat function */
#define HAVE_STAT #define HAVE_STAT
/* Define if we have the powf function */ /* Define if we have the lrintf function */
/* #define HAVE_POWF 1 */ #define HAVE_LRINTF
/* Define if we have the sqrtf function */
/* #define HAVE_SQRTF 1 */
/* Define if we have the cosf function */
/* #define HAVE_COSF 1 */
/* Define if we have the sinf function */
/* #define HAVE_SINF 1 */
/* Define if we have the acosf function */
/* #define HAVE_ACOSF 1 */
/* Define if we have the asinf function */
/* #define HAVE_ASINF 1 */
/* Define if we have the atanf function */
/* #define HAVE_ATANF 1 */
/* Define if we have the atan2f function */
/* #define HAVE_ATAN2F 1 */
/* Define if we have the fabsf function */
/* #define HAVE_FABSF 1 */
/* Define if we have the log10f function */
/* #define HAVE_LOG10F 1 */
/* Define if we have the floorf function */
/* #define HAVE_FLOORF 1 */
/* Define if we have the strtof function */ /* Define if we have the strtof function */
#define HAVE_STRTOF /* #undef HAVE_STRTOF */
/* Define if we have stdint.h */
#define HAVE_STDINT_H
/* Define if we have the __int64 type */ /* Define if we have the __int64 type */
/* #cmakedefine HAVE___INT64 */ /* #undef HAVE___INT64 */
/* Define to the size of a long int type */ /* Define to the size of a long int type */
#define SIZEOF_LONG 4 #define SIZEOF_LONG 4
@ -99,49 +91,113 @@
/* Define to the size of a long long int type */ /* Define to the size of a long long int type */
#define SIZEOF_LONG_LONG 8 #define SIZEOF_LONG_LONG 8
/* Define if we have C99 variable-length array support */
#define HAVE_C99_VLA
/* Define if we have C99 _Bool support */
#define HAVE_C99_BOOL
/* Define if we have C11 _Static_assert support */
#define HAVE_C11_STATIC_ASSERT
/* Define if we have C11 _Alignas support */
/* #undef HAVE_C11_ALIGNAS */
/* Define if we have C11 _Atomic support */
/* #undef HAVE_C11_ATOMIC */
/* Define if we have GCC's destructor attribute */ /* Define if we have GCC's destructor attribute */
#define HAVE_GCC_DESTRUCTOR #define HAVE_GCC_DESTRUCTOR
/* Define if we have GCC's format attribute */ /* Define if we have GCC's format attribute */
#define HAVE_GCC_FORMAT #define HAVE_GCC_FORMAT
/* Define if we have stdint.h */
#define HAVE_STDINT_H
/* Define if we have stdbool.h */
#define HAVE_STDBOOL_H
/* Define if we have stdalign.h */
/* #undef HAVE_STDALIGN_H */
/* Define if we have windows.h */
/* #undef HAVE_WINDOWS_H */
/* Define if we have dlfcn.h */
#define HAVE_DLFCN_H
/* Define if we have pthread_np.h */ /* Define if we have pthread_np.h */
/* #cmakedefine HAVE_PTHREAD_NP_H */ /* #undef HAVE_PTHREAD_NP_H */
/* Define if we have arm_neon.h */ /* Define if we have alloca.h */
/* #cmakedefine HAVE_ARM_NEON_H */ /* #undef HAVE_ALLOCA_H */
/* Define if we have malloc.h */
#define HAVE_MALLOC_H
/* Define if we have ftw.h */
/* #undef HAVE_FTW_H */
/* Define if we have io.h */
/* #undef HAVE_IO_H */
/* Define if we have strings.h */
#define HAVE_STRINGS_H
/* Define if we have cpuid.h */
/* #undef HAVE_CPUID_H */
/* Define if we have intrin.h */
/* #undef HAVE_INTRIN_H */
/* Define if we have sys/sysconf.h */
#define HAVE_SYS_SYSCONF_H
/* Define if we have guiddef.h */ /* Define if we have guiddef.h */
/* #cmakedefine HAVE_GUIDDEF_H */ /* #undef HAVE_GUIDDEF_H */
/* Define if we have guiddef.h */ /* Define if we have initguid.h */
/* #cmakedefine HAVE_INITGUID_H */ /* #undef HAVE_INITGUID_H */
/* Define if we have ieeefp.h */ /* Define if we have ieeefp.h */
/* #cmakedefine HAVE_IEEEFP_H */ /* #undef HAVE_IEEEFP_H */
/* Define if we have float.h */ /* Define if we have float.h */
/* #cmakedefine HAVE_FLOAT_H */ #define HAVE_FLOAT_H
/* Define if we have fpu_control.h */
/* #cmakedefine HAVE_FPU_CONTROL_H */
/* Define if we have fenv.h */ /* Define if we have fenv.h */
#define HAVE_FENV_H #define HAVE_FENV_H
/* Define if we have fesetround() */ /* Define if we have GCC's __get_cpuid() */
/* #cmakedefine HAVE_FESETROUND */ /* #undef HAVE_GCC_GET_CPUID */
/* Define if we have the __cpuid() intrinsic */
/* #undef HAVE_CPUID_INTRINSIC */
/* Define if we have _controlfp() */ /* Define if we have _controlfp() */
/* #cmakedefine HAVE__CONTROLFP */ /* #undef HAVE__CONTROLFP */
/* Define if we have __control87_2() */
/* #undef HAVE___CONTROL87_2 */
/* Define if we have ftw() */
/* #undef HAVE_FTW */
/* Define if we have _wfindfirst() */
/* #undef HAVE__WFINDFIRST */
/* Define if we have pthread_setschedparam() */ /* Define if we have pthread_setschedparam() */
#define HAVE_PTHREAD_SETSCHEDPARAM #define HAVE_PTHREAD_SETSCHEDPARAM
/* Define if we have the restrict keyword */ /* Define if we have pthread_setname_np() */
/* #cmakedefine HAVE_RESTRICT 1 */ #define HAVE_PTHREAD_SETNAME_NP
/* Define if we have the __restrict keyword */ /* Define if we have pthread_set_name_np() */
#define RESTRICT __restrict /* #undef HAVE_PTHREAD_SET_NAME_NP */
#endif /* Define if we have pthread_mutexattr_setkind_np() */
/* #undef HAVE_PTHREAD_MUTEXATTR_SETKIND_NP */
/* Define if we have pthread_mutex_timedlock() */
/* #undef HAVE_PTHREAD_MUTEX_TIMEDLOCK */

View File

@ -1,13 +1,15 @@
TARGET_PLATFORM := android-9
LOCAL_PATH := $(call my-dir) LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) include $(CLEAR_VARS)
LOCAL_MODULE := stbijme LOCAL_MODULE := stbijme
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS += -O2
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
LOCAL_SRC_FILES := $(subst $(LOCAL_PATH)/,, $(wildcard $(LOCAL_PATH)/*.c))
#adds zlib LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_LDLIBS += -lz -llog
LOCAL_LDLIBS := -lz -llog -Wl,-s
LOCAL_SRC_FILES := com_jme3_texture_plugins_AndroidNativeImageLoader.c
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View File

@ -1,3 +1,3 @@
APP_PLATFORM := android-9
APP_OPTIM := release APP_OPTIM := release
APP_ABI := all APP_ABI := all
#APP_ABI := armeabi-v7a

View File

@ -6,8 +6,9 @@
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#define STBI_HEADER_FILE_ONLY
#include "stb_image.c" #define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
typedef unsigned int uint32; typedef unsigned int uint32;

View File

@ -1,6 +1,6 @@
// stb_image url for download // stb_image url for download
String stbiUrl = 'http://www.nothings.org/stb_image.c' String stbiUrl = 'https://raw.githubusercontent.com/nothings/stb/master/stb_image.h'
String stbiDownloadTarget = 'stb_image.c' String stbiDownloadTarget = 'stb_image.h'
// stb_image is not downloaded. The single source file is included in the repo // stb_image is not downloaded. The single source file is included in the repo
String stbiFolder = 'stb_image' String stbiFolder = 'stb_image'
@ -63,20 +63,21 @@ task generateStbiHeaders(dependsOn: copyStbiJmeFiles) << {
// println "stb_image destDir = " + destDir // println "stb_image destDir = " + destDir
// println "stb_image classpath = " + project.projectClassPath // println "stb_image classpath = " + project.projectClassPath
ant.javah( exec {
classpath: project.projectClassPath, executable org.gradle.internal.jvm.Jvm.current().getExecutable('javah')
destdir: destDirPath, args '-d', destDirPath
class: classes args '-classpath', project.projectClassPath
) args "com.jme3.texture.plugins.AndroidNativeImageLoader"
}
} }
task buildStbiNativeLib(type: Exec, dependsOn: generateStbiHeaders) { task buildStbiNativeLib(type: Exec, dependsOn: generateStbiHeaders) {
// println "stb_image build dir: " + buildLibDir // println "stb_image build dir: " + stbiBuildDir
// println "ndkCommandPath: " + project.ndkCommandPath // println "ndkCommandPath: " + rootProject.ndkCommandPath
args 'TARGET_PLATFORM=android-9'
workingDir stbiBuildDir workingDir stbiBuildDir
executable rootProject.ndkCommandPath executable rootProject.ndkCommandPath
args '-j8'
} }
task updatePreCompiledStbiLibs(type: Copy, dependsOn: buildStbiNativeLib) { task updatePreCompiledStbiLibs(type: Copy, dependsOn: buildStbiNativeLib) {

View File

@ -6,6 +6,7 @@ import android.content.DialogInterface;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable; import android.graphics.drawable.NinePatchDrawable;
import android.opengl.GLSurfaceView;
import android.os.Bundle; import android.os.Bundle;
import android.util.Log; import android.util.Log;
import android.view.*; import android.view.*;
@ -21,7 +22,6 @@ import com.jme3.input.android.AndroidSensorJoyInput;
import com.jme3.input.controls.TouchListener; import com.jme3.input.controls.TouchListener;
import com.jme3.input.controls.TouchTrigger; import com.jme3.input.controls.TouchTrigger;
import com.jme3.input.event.TouchEvent; import com.jme3.input.event.TouchEvent;
import com.jme3.renderer.android.AndroidGLSurfaceView;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import com.jme3.system.SystemListener; import com.jme3.system.SystemListener;
import com.jme3.system.android.AndroidConfigChooser.ConfigType; import com.jme3.system.android.AndroidConfigChooser.ConfigType;
@ -195,7 +195,7 @@ public class AndroidHarness extends Activity implements TouchListener, DialogInt
*/ */
protected int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR; protected int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
protected OGLESContext ctx; protected OGLESContext ctx;
protected AndroidGLSurfaceView view = null; protected GLSurfaceView view = null;
protected boolean isGLThreadPaused = true; protected boolean isGLThreadPaused = true;
protected ImageView splashImageView = null; protected ImageView splashImageView = null;
protected FrameLayout frameLayout = null; protected FrameLayout frameLayout = null;

View File

@ -32,6 +32,7 @@
package com.jme3.input.android; package com.jme3.input.android;
import android.opengl.GLSurfaceView;
import android.os.Build; import android.os.Build;
import android.view.View; import android.view.View;
import com.jme3.input.RawInputListener; import com.jme3.input.RawInputListener;
@ -41,7 +42,6 @@ import com.jme3.input.event.KeyInputEvent;
import com.jme3.input.event.MouseButtonEvent; import com.jme3.input.event.MouseButtonEvent;
import com.jme3.input.event.MouseMotionEvent; import com.jme3.input.event.MouseMotionEvent;
import com.jme3.input.event.TouchEvent; import com.jme3.input.event.TouchEvent;
import com.jme3.renderer.android.AndroidGLSurfaceView;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level; import java.util.logging.Level;
@ -67,7 +67,7 @@ public class AndroidInputHandler implements TouchInput {
// Internal // Internal
private AndroidGLSurfaceView view; private GLSurfaceView view;
private AndroidTouchHandler touchHandler; private AndroidTouchHandler touchHandler;
private AndroidKeyHandler keyHandler; private AndroidKeyHandler keyHandler;
private AndroidGestureHandler gestureHandler; private AndroidGestureHandler gestureHandler;
@ -112,7 +112,7 @@ public class AndroidInputHandler implements TouchInput {
if (gestureHandler != null) { if (gestureHandler != null) {
gestureHandler.setView(view); gestureHandler.setView(view);
} }
this.view = (AndroidGLSurfaceView)view; this.view = (GLSurfaceView)view;
} }
public View getView() { public View getView() {

View File

@ -1,26 +0,0 @@
package com.jme3.renderer.android;
import android.content.Context;
import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
import java.util.logging.Logger;
/**
* <code>AndroidGLSurfaceView</code> is derived from GLSurfaceView
* @author iwgeric
*
*/
public class AndroidGLSurfaceView extends GLSurfaceView {
private final static Logger logger = Logger.getLogger(AndroidGLSurfaceView.class.getName());
public AndroidGLSurfaceView(Context ctx, AttributeSet attribs) {
super(ctx, attribs);
}
public AndroidGLSurfaceView(Context ctx) {
super(ctx);
}
}

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.system.android;
import com.jme3.system.Timer;
/**
* <code>AndroidTimer</code> is a System.nanoTime implementation of <code>Timer</code>.
*/
public class AndroidTimer extends Timer {
//private static final long TIMER_RESOLUTION = 1000L;
//private static final float INVERSE_TIMER_RESOLUTION = 1f/1000L;
private static final long TIMER_RESOLUTION = 1000000000L;
private static final float INVERSE_TIMER_RESOLUTION = 1f/1000000000L;
private long startTime;
private long previousTime;
private float tpf;
private float fps;
public AndroidTimer() {
//startTime = System.currentTimeMillis();
startTime = System.nanoTime();
}
/**
* Returns the time in seconds. The timer starts
* at 0.0 seconds.
*
* @return the current time in seconds
*/
@Override
public float getTimeInSeconds() {
return getTime() * INVERSE_TIMER_RESOLUTION;
}
public long getTime() {
//return System.currentTimeMillis() - startTime;
return System.nanoTime() - startTime;
}
public long getResolution() {
return TIMER_RESOLUTION;
}
public float getFrameRate() {
return fps;
}
public float getTimePerFrame() {
return tpf;
}
public void update() {
tpf = (getTime() - previousTime) * (1.0f / TIMER_RESOLUTION);
fps = 1.0f / tpf;
previousTime = getTime();
}
public void reset() {
//startTime = System.currentTimeMillis();
startTime = System.nanoTime();
previousTime = getTime();
}
}

View File

@ -47,13 +47,11 @@ import android.view.ViewGroup.LayoutParams;
import android.widget.EditText; import android.widget.EditText;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import com.jme3.input.*; import com.jme3.input.*;
import com.jme3.input.android.AndroidInput;
import com.jme3.input.android.AndroidSensorJoyInput; import com.jme3.input.android.AndroidSensorJoyInput;
import com.jme3.input.android.AndroidInputHandler; import com.jme3.input.android.AndroidInputHandler;
import com.jme3.input.controls.SoftTextDialogInputListener; import com.jme3.input.controls.SoftTextDialogInputListener;
import com.jme3.input.dummy.DummyKeyInput; import com.jme3.input.dummy.DummyKeyInput;
import com.jme3.input.dummy.DummyMouseInput; import com.jme3.input.dummy.DummyMouseInput;
import com.jme3.renderer.android.AndroidGLSurfaceView;
import com.jme3.renderer.android.OGLESShaderRenderer; import com.jme3.renderer.android.OGLESShaderRenderer;
import com.jme3.system.*; import com.jme3.system.*;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -80,11 +78,6 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
protected AndroidInputHandler androidInput; protected AndroidInputHandler androidInput;
protected int minFrameDuration = 0; // No FPS cap protected int minFrameDuration = 0; // No FPS cap
protected JoyInput androidSensorJoyInput = null; protected JoyInput androidSensorJoyInput = null;
/**
* EGL_RENDERABLE_TYPE: EGL_OPENGL_ES_BIT = OpenGL ES 1.0 |
* EGL_OPENGL_ES2_BIT = OpenGL ES 2.0
*/
protected int clientOpenGLESVersion = 1;
public OGLESContext() { public OGLESContext() {
} }
@ -103,12 +96,17 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
* *
* @return GLSurfaceView The newly created view * @return GLSurfaceView The newly created view
*/ */
public AndroidGLSurfaceView createView() { public GLSurfaceView createView() {
AndroidGLSurfaceView view; Context appContext = JmeAndroidSystem.getActivity().getApplication();
int buildVersion = Build.VERSION.SDK_INT;
ActivityManager am = (ActivityManager) appContext.getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
if (info.reqGlEsVersion < 0x20000) {
throw new UnsupportedOperationException("OpenGL ES 2.0 is not supported on this device");
}
// Start to set up the view // Start to set up the view
view = new AndroidGLSurfaceView(JmeAndroidSystem.getActivity().getApplication()); GLSurfaceView view = new GLSurfaceView(appContext);
if (androidInput == null) { if (androidInput == null) {
androidInput = new AndroidInputHandler(); androidInput = new AndroidInputHandler();
} }
@ -117,19 +115,10 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
// setEGLContextClientVersion must be set before calling setRenderer // setEGLContextClientVersion must be set before calling setRenderer
// this means it cannot be set in AndroidConfigChooser (too late) // this means it cannot be set in AndroidConfigChooser (too late)
int rawOpenGLESVersion = getOpenGLESVersion(); view.setEGLContextClientVersion(2);
// logger.log(Level.FINE, "clientOpenGLESVersion {0}.{1}",
// new Object[]{clientOpenGLESVersion>>16, clientOpenGLESVersion<<16});
if (rawOpenGLESVersion < 0x20000) {
throw new UnsupportedOperationException("OpenGL ES 2.0 is not supported on this device");
} else {
clientOpenGLESVersion = 2;
view.setEGLContextClientVersion(clientOpenGLESVersion);
}
view.setFocusableInTouchMode(true); view.setFocusableInTouchMode(true);
view.setFocusable(true); view.setFocusable(true);
view.getHolder().setType(SurfaceHolder.SURFACE_TYPE_GPU);
// setFormat must be set before AndroidConfigChooser is called by the surfaceview. // setFormat must be set before AndroidConfigChooser is called by the surfaceview.
// if setFormat is called after ConfigChooser is called, then execution // if setFormat is called after ConfigChooser is called, then execution
@ -160,24 +149,12 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
// Not destroying and recreating the EGL context // Not destroying and recreating the EGL context
// will help with resume time by reusing the existing context to avoid // will help with resume time by reusing the existing context to avoid
// reloading all the OpenGL objects. // reloading all the OpenGL objects.
if (buildVersion >= 11) { if (Build.VERSION.SDK_INT >= 11) {
view.setPreserveEGLContextOnPause(true); view.setPreserveEGLContextOnPause(true);
} }
return view; return view;
} }
/**
* Get the OpenGL ES version
* @return version returns the int value of the GLES version
*/
public int getOpenGLESVersion() {
ActivityManager am =
(ActivityManager) JmeAndroidSystem.getActivity().getApplication().getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
logger.log(Level.FINE, "OpenGL Version {0}:", info.getGlEsVersion());
return info.reqGlEsVersion;
// return (info.reqGlEsVersion >= 0x20000);
}
// renderer:initialize // renderer:initialize
@Override @Override
@ -207,7 +184,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
} }
}); });
timer = new AndroidTimer(); timer = new NanoTimer();
renderer = new OGLESShaderRenderer(); renderer = new OGLESShaderRenderer();
renderer.initialize(); renderer.initialize();

View File

@ -42,7 +42,6 @@ import com.jme3.material.TechniqueDef.LightMode;
import com.jme3.material.TechniqueDef.ShadowMode; import com.jme3.material.TechniqueDef.ShadowMode;
import com.jme3.math.*; import com.jme3.math.*;
import com.jme3.renderer.Caps; import com.jme3.renderer.Caps;
import com.jme3.renderer.GL1Renderer;
import com.jme3.renderer.RenderManager; import com.jme3.renderer.RenderManager;
import com.jme3.renderer.Renderer; import com.jme3.renderer.Renderer;
import com.jme3.renderer.RendererException; import com.jme3.renderer.RendererException;
@ -52,7 +51,6 @@ import com.jme3.scene.Mesh;
import com.jme3.scene.instancing.InstancedGeometry; import com.jme3.scene.instancing.InstancedGeometry;
import com.jme3.shader.Shader; import com.jme3.shader.Shader;
import com.jme3.shader.Uniform; import com.jme3.shader.Uniform;
import com.jme3.shader.UniformBindingManager;
import com.jme3.shader.VarType; import com.jme3.shader.VarType;
import com.jme3.texture.Texture; import com.jme3.texture.Texture;
import com.jme3.texture.image.ColorSpace; import com.jme3.texture.image.ColorSpace;
@ -697,12 +695,15 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
setParam(name, VarType.Vector4, value); setParam(name, VarType.Vector4, value);
} }
private ColorRGBA getAmbientColor(LightList lightList) { private ColorRGBA getAmbientColor(LightList lightList, boolean removeLights) {
ambientLightColor.set(0, 0, 0, 1); ambientLightColor.set(0, 0, 0, 1);
for (int j = 0; j < lightList.size(); j++) { for (int j = 0; j < lightList.size(); j++) {
Light l = lightList.get(j); Light l = lightList.get(j);
if (l instanceof AmbientLight) { if (l instanceof AmbientLight) {
ambientLightColor.addLocal(l.getColor()); ambientLightColor.addLocal(l.getColor());
if(removeLights){
lightList.remove(l);
}
} }
} }
ambientLightColor.a = 1.0f; ambientLightColor.a = 1.0f;
@ -741,47 +742,73 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
* g_LightPosition.w is the inverse radius (1/r) of the light (for * g_LightPosition.w is the inverse radius (1/r) of the light (for
* attenuation) <br/> </p> * attenuation) <br/> </p>
*/ */
protected void updateLightListUniforms(Shader shader, Geometry g, LightList lightList, int numLights) { protected int updateLightListUniforms(Shader shader, Geometry g, LightList lightList, int numLights, RenderManager rm, int startIndex) {
if (numLights == 0) { // this shader does not do lighting, ignore. if (numLights == 0) { // this shader does not do lighting, ignore.
return; return 0;
} }
Uniform lightColor = shader.getUniform("g_LightColor"); Uniform lightData = shader.getUniform("g_LightData");
Uniform lightPos = shader.getUniform("g_LightPosition"); lightData.setVector4Length(numLights * 3);//8 lights * max 3
Uniform lightDir = shader.getUniform("g_LightDirection");
lightColor.setVector4Length(numLights);
lightPos.setVector4Length(numLights);
lightDir.setVector4Length(numLights);
Uniform ambientColor = shader.getUniform("g_AmbientLightColor"); Uniform ambientColor = shader.getUniform("g_AmbientLightColor");
ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList));
int lightIndex = 0;
for (int i = 0; i < numLights; i++) { if (startIndex != 0) {
if (lightList.size() <= i) { // apply additive blending for 2nd and future passes
lightColor.setVector4InArray(0f, 0f, 0f, 0f, lightIndex); rm.getRenderer().applyRenderState(additiveLight);
lightPos.setVector4InArray(0f, 0f, 0f, 0f, lightIndex); ambientColor.setValue(VarType.Vector4, ColorRGBA.Black);
}else{ }else{
Light l = lightList.get(i); ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList,true));
}
int lightDataIndex = 0;
TempVars vars = TempVars.get();
Vector4f tmpVec = vars.vect4f1;
int curIndex;
int endIndex = numLights + startIndex;
for (curIndex = startIndex; curIndex < endIndex && curIndex < lightList.size(); curIndex++) {
Light l = lightList.get(curIndex);
if(l.getType() == Light.Type.Ambient){
endIndex++;
continue;
}
ColorRGBA color = l.getColor(); ColorRGBA color = l.getColor();
lightColor.setVector4InArray(color.getRed(), //Color
lightData.setVector4InArray(color.getRed(),
color.getGreen(), color.getGreen(),
color.getBlue(), color.getBlue(),
l.getType().getId(), l.getType().getId(),
i); lightDataIndex);
lightDataIndex++;
switch (l.getType()) { switch (l.getType()) {
case Directional: case Directional:
DirectionalLight dl = (DirectionalLight) l; DirectionalLight dl = (DirectionalLight) l;
Vector3f dir = dl.getDirection(); Vector3f dir = dl.getDirection();
lightPos.setVector4InArray(dir.getX(), dir.getY(), dir.getZ(), -1, lightIndex); //Data directly sent in view space to avoid a matrix mult for each pixel
tmpVec.set(dir.getX(), dir.getY(), dir.getZ(), 0.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
// tmpVec.divideLocal(tmpVec.w);
// tmpVec.normalizeLocal();
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), -1, lightDataIndex);
lightDataIndex++;
//PADDING
lightData.setVector4InArray(0,0,0,0, lightDataIndex);
lightDataIndex++;
break; break;
case Point: case Point:
PointLight pl = (PointLight) l; PointLight pl = (PointLight) l;
Vector3f pos = pl.getPosition(); Vector3f pos = pl.getPosition();
float invRadius = pl.getInvRadius(); float invRadius = pl.getInvRadius();
lightPos.setVector4InArray(pos.getX(), pos.getY(), pos.getZ(), invRadius, lightIndex); tmpVec.set(pos.getX(), pos.getY(), pos.getZ(), 1.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
//tmpVec.divideLocal(tmpVec.w);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRadius, lightDataIndex);
lightDataIndex++;
//PADDING
lightData.setVector4InArray(0,0,0,0, lightDataIndex);
lightDataIndex++;
break; break;
case Spot: case Spot:
SpotLight sl = (SpotLight) l; SpotLight sl = (SpotLight) l;
@ -789,27 +816,32 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
Vector3f dir2 = sl.getDirection(); Vector3f dir2 = sl.getDirection();
float invRange = sl.getInvSpotRange(); float invRange = sl.getInvSpotRange();
float spotAngleCos = sl.getPackedAngleCos(); float spotAngleCos = sl.getPackedAngleCos();
tmpVec.set(pos2.getX(), pos2.getY(), pos2.getZ(), 1.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
// tmpVec.divideLocal(tmpVec.w);
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), invRange, lightDataIndex);
lightDataIndex++;
lightPos.setVector4InArray(pos2.getX(), pos2.getY(), pos2.getZ(), invRange, lightIndex); //We transform the spot direction in view space here to save 5 varying later in the lighting shader
lightDir.setVector4InArray(dir2.getX(), dir2.getY(), dir2.getZ(), spotAngleCos, lightIndex); //one vec4 less and a vec4 that becomes a vec3
//the downside is that spotAngleCos decoding happens now in the frag shader.
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0.0f);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
tmpVec.normalizeLocal();
lightData.setVector4InArray(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos, lightDataIndex);
lightDataIndex++;
break; break;
case Ambient:
// skip this light. Does not increase lightIndex
continue;
default: default:
throw new UnsupportedOperationException("Unknown type of light: " + l.getType()); throw new UnsupportedOperationException("Unknown type of light: " + l.getType());
} }
} }
vars.release();
lightIndex++; //Padding of unsued buffer space
} while(lightDataIndex < numLights * 3) {
lightData.setVector4InArray(0f, 0f, 0f, 0f, lightDataIndex);
while (lightIndex < numLights) { lightDataIndex++;
lightColor.setVector4InArray(0f, 0f, 0f, 0f, lightIndex);
lightPos.setVector4InArray(0f, 0f, 0f, 0f, lightIndex);
lightIndex++;
} }
return curIndex;
} }
protected void renderMultipassLighting(Shader shader, Geometry g, LightList lightList, RenderManager rm) { protected void renderMultipassLighting(Shader shader, Geometry g, LightList lightList, RenderManager rm) {
@ -830,7 +862,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
if (isFirstLight) { if (isFirstLight) {
// set ambient color for first light only // set ambient color for first light only
ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList)); ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList, false));
isFirstLight = false; isFirstLight = false;
isSecondLight = true; isSecondLight = true;
} else if (isSecondLight) { } else if (isSecondLight) {
@ -885,9 +917,9 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange); tmpLightPosition.set(pos2.getX(), pos2.getY(), pos2.getZ(), invRange);
lightPos.setValue(VarType.Vector4, tmpLightPosition); lightPos.setValue(VarType.Vector4, tmpLightPosition);
//We transform the spot directoin in view space here to save 5 varying later in the lighting shader //We transform the spot direction in view space here to save 5 varying later in the lighting shader
//one vec4 less and a vec4 that becomes a vec3 //one vec4 less and a vec4 that becomes a vec3
//the downside is that spotAngleCos decoding happen now in the frag shader. //the downside is that spotAngleCos decoding happens now in the frag shader.
tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0); tmpVec.set(dir2.getX(), dir2.getY(), dir2.getZ(), 0);
rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec); rm.getCurrentCamera().getViewMatrix().mult(tmpVec, tmpVec);
tmpLightDirection.set(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos); tmpLightDirection.set(tmpVec.getX(), tmpVec.getY(), tmpVec.getZ(), spotAngleCos);
@ -906,7 +938,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
if (isFirstLight && lightList.size() > 0) { if (isFirstLight && lightList.size() > 0) {
// There are only ambient lights in the scene. Render // There are only ambient lights in the scene. Render
// a dummy "normal light" so we can see the ambient // a dummy "normal light" so we can see the ambient
ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList)); ambientColor.setValue(VarType.Vector4, getAmbientColor(lightList, false));
lightColor.setValue(VarType.Vector4, ColorRGBA.BlackNoAlpha); lightColor.setValue(VarType.Vector4, ColorRGBA.BlackNoAlpha);
lightPos.setValue(VarType.Vector4, nullDirLight); lightPos.setValue(VarType.Vector4, nullDirLight);
r.setShader(shader); r.setShader(shader);
@ -957,8 +989,11 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
// use the first one that supports all the caps // use the first one that supports all the caps
tech = new Technique(this, techDef); tech = new Technique(this, techDef);
techniques.put(name, tech); techniques.put(name, tech);
if(tech.getDef().getLightMode() == renderManager.getPreferredLightMode() ||
tech.getDef().getLightMode() == LightMode.Disable){
break; break;
} }
}
lastTech = techDef; lastTech = techDef;
} }
if (tech == null) { if (tech == null) {
@ -990,7 +1025,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
} }
technique = tech; technique = tech;
tech.makeCurrent(def.getAssetManager(), true, rendererCaps); tech.makeCurrent(def.getAssetManager(), true, rendererCaps, renderManager);
// shader was changed // shader was changed
sortingId = -1; sortingId = -1;
@ -1000,7 +1035,7 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
if (technique == null) { if (technique == null) {
selectTechnique("Default", rm); selectTechnique("Default", rm);
} else { } else {
technique.makeCurrent(def.getAssetManager(), false, rm.getRenderer().getCaps()); technique.makeCurrent(def.getAssetManager(), false, rm.getRenderer().getCaps(), rm);
} }
} }
@ -1162,8 +1197,14 @@ public class Material implements CloneableSmartAsset, Cloneable, Savable {
r.setLighting(null); r.setLighting(null);
break; break;
case SinglePass: case SinglePass:
updateLightListUniforms(shader, geom, lights, 4); int nbRenderedLights = 0;
break; resetUniformsNotSetByCurrent(shader);
while(nbRenderedLights < lights.size()){
nbRenderedLights = updateLightListUniforms(shader, geom, lights, rm.getSinglePassLightBatchSize(), rm, nbRenderedLights);
r.setShader(shader);
renderMeshFromGeometry(r, geom);
}
return;
case FixedPipeline: case FixedPipeline:
r.setLighting(lights); r.setLighting(lights);
break; break;

View File

@ -33,8 +33,8 @@ package com.jme3.material;
import com.jme3.asset.AssetManager; import com.jme3.asset.AssetManager;
import com.jme3.renderer.Caps; import com.jme3.renderer.Caps;
import com.jme3.renderer.RenderManager;
import com.jme3.shader.*; import com.jme3.shader.*;
import com.jme3.util.ListMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
@ -172,7 +172,7 @@ public class Technique /* implements Savable */ {
* *
* @param assetManager The asset manager to use for loading shaders. * @param assetManager The asset manager to use for loading shaders.
*/ */
public void makeCurrent(AssetManager assetManager, boolean techniqueSwitched, EnumSet<Caps> rendererCaps) { public void makeCurrent(AssetManager assetManager, boolean techniqueSwitched, EnumSet<Caps> rendererCaps, RenderManager rm) {
if (!def.isUsingShaders()) { if (!def.isUsingShaders()) {
// No shaders are used, no processing is neccessary. // No shaders are used, no processing is neccessary.
return; return;
@ -182,6 +182,13 @@ public class Technique /* implements Savable */ {
if (defines.update(owner.getParamsMap(), def)) { if (defines.update(owner.getParamsMap(), def)) {
needReload = true; needReload = true;
} }
if(getDef().getLightMode()== TechniqueDef.LightMode.SinglePass){
defines.set("SINGLE_PASS_LIGHTING", VarType.Boolean, true);
defines.set("NB_LIGHTS", VarType.Int, rm.getSinglePassLightBatchSize()*3 );
}else{
defines.set("SINGLE_PASS_LIGHTING", VarType.Boolean, null);
}
} }
if (needReload) { if (needReload) {

View File

@ -236,7 +236,22 @@ public enum Caps {
/** /**
* Supports sRGB framebuffers and sRGB texture format * Supports sRGB framebuffers and sRGB texture format
*/ */
Srgb; Srgb,
/**
* Supports blitting framebuffers.
*/
FrameBufferBlit,
/**
* Supports {@link Format#DXT1} and sister formats.
*/
TextureCompressionS3TC,
/**
* Supports anisotropic texture filtering.
*/
TextureFilterAnisotropic;
/** /**
* Returns true if given the renderer capabilities, the texture * Returns true if given the renderer capabilities, the texture

View File

@ -35,6 +35,7 @@ import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA; import com.jme3.math.ColorRGBA;
import com.jme3.scene.Mesh; import com.jme3.scene.Mesh;
import com.jme3.scene.VertexBuffer; import com.jme3.scene.VertexBuffer;
import com.jme3.shader.Shader;
import com.jme3.texture.FrameBuffer; import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image; import com.jme3.texture.Image;
@ -139,11 +140,21 @@ public class RenderContext {
*/ */
public int boundShaderProgram; public int boundShaderProgram;
/**
* @see Renderer#setShader(com.jme3.shader.Shader)
*/
public Shader boundShader;
/** /**
* @see Renderer#setFrameBuffer(com.jme3.texture.FrameBuffer) * @see Renderer#setFrameBuffer(com.jme3.texture.FrameBuffer)
*/ */
public int boundFBO = 0; public int boundFBO = 0;
/**
* @see Renderer#setFrameBuffer(com.jme3.texture.FrameBuffer)
*/
public FrameBuffer boundFB;
/** /**
* Currently bound Renderbuffer * Currently bound Renderbuffer
* *
@ -279,6 +290,10 @@ public class RenderContext {
*/ */
public RenderState.TestFunction alphaFunc = RenderState.TestFunction.Greater; public RenderState.TestFunction alphaFunc = RenderState.TestFunction.Greater;
public int initialDrawBuf;
public int initialReadBuf;
/** /**
* Reset the RenderContext to default GL state * Reset the RenderContext to default GL state
*/ */
@ -298,7 +313,9 @@ public class RenderContext {
blendMode = RenderState.BlendMode.Off; blendMode = RenderState.BlendMode.Off;
wireframe = false; wireframe = false;
boundShaderProgram = 0; boundShaderProgram = 0;
boundShader = null;
boundFBO = 0; boundFBO = 0;
boundFB = null;
boundRB = 0; boundRB = 0;
boundDrawBuf = -1; boundDrawBuf = -1;
boundReadBuf = -1; boundReadBuf = -1;

View File

@ -38,6 +38,7 @@ import com.jme3.material.Material;
import com.jme3.material.MaterialDef; import com.jme3.material.MaterialDef;
import com.jme3.material.RenderState; import com.jme3.material.RenderState;
import com.jme3.material.Technique; import com.jme3.material.Technique;
import com.jme3.material.TechniqueDef;
import com.jme3.math.*; import com.jme3.math.*;
import com.jme3.post.SceneProcessor; import com.jme3.post.SceneProcessor;
import com.jme3.profile.AppProfiler; import com.jme3.profile.AppProfiler;
@ -89,6 +90,8 @@ public class RenderManager {
private boolean handleTranlucentBucket = true; private boolean handleTranlucentBucket = true;
private AppProfiler prof; private AppProfiler prof;
private LightFilter lightFilter = new DefaultLightFilter(); private LightFilter lightFilter = new DefaultLightFilter();
private TechniqueDef.LightMode preferredLightMode = TechniqueDef.LightMode.MultiPass;
private int singlePassLightBatchSize = 1;
/** /**
* Create a high-level rendering interface over the * Create a high-level rendering interface over the
@ -780,6 +783,33 @@ public class RenderManager {
vp.getQueue().clear(); vp.getQueue().clear();
} }
/**
* Sets the light filter to use when rendering Lighted Geometries
*
* @see LightFilter
* @param lightFilter The light filter tose. Set it to null if you want all lights to be rendered
*/
public void setLightFilter(LightFilter lightFilter) {
this.lightFilter = lightFilter;
}
public void setPreferredLightMode(TechniqueDef.LightMode preferredLightMode) {
this.preferredLightMode = preferredLightMode;
}
public TechniqueDef.LightMode getPreferredLightMode() {
return preferredLightMode;
}
public int getSinglePassLightBatchSize() {
return singlePassLightBatchSize;
}
public void setSinglePassLightBatchSize(int singlePassLightBatchSize) {
this.singlePassLightBatchSize = singlePassLightBatchSize;
}
/** /**
* Render the given viewport queues. * Render the given viewport queues.
* <p> * <p>

View File

@ -1,7 +1,9 @@
#import "Common/ShaderLib/Parallax.glsllib" #import "Common/ShaderLib/Parallax.glsllib"
#import "Common/ShaderLib/Optics.glsllib" #import "Common/ShaderLib/Optics.glsllib"
#define ATTENUATION #ifndef VERTEX_LIGHTING
//#define HQ_ATTENUATION #import "Common/ShaderLib/PhongLighting.glsllib"
#import "Common/ShaderLib/Lighting.glsllib"
#endif
varying vec2 texCoord; varying vec2 texCoord;
#ifdef SEPARATE_TEXCOORD #ifdef SEPARATE_TEXCOORD
@ -59,11 +61,6 @@ uniform float m_AlphaDiscardThreshold;
#ifndef VERTEX_LIGHTING #ifndef VERTEX_LIGHTING
uniform float m_Shininess; uniform float m_Shininess;
#ifdef HQ_ATTENUATION
uniform vec4 g_LightPosition;
#endif
#ifdef USE_REFLECTION #ifdef USE_REFLECTION
uniform float m_ReflectionPower; uniform float m_ReflectionPower;
uniform float m_ReflectionIntensity; uniform float m_ReflectionIntensity;
@ -71,69 +68,6 @@ uniform vec4 g_LightPosition;
uniform ENVMAP m_EnvMap; uniform ENVMAP m_EnvMap;
#endif #endif
float tangDot(in vec3 v1, in vec3 v2){
float d = dot(v1,v2);
#ifdef V_TANGENT
d = 1.0 - d*d;
return step(0.0, d) * sqrt(d);
#else
return d;
#endif
}
float lightComputeDiffuse(in vec3 norm, in vec3 lightdir, in vec3 viewdir){
#ifdef MINNAERT
float NdotL = max(0.0, dot(norm, lightdir));
float NdotV = max(0.0, dot(norm, viewdir));
return NdotL * pow(max(NdotL * NdotV, 0.1), -1.0) * 0.5;
#else
return max(0.0, dot(norm, lightdir));
#endif
}
float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
// NOTE: check for shiny <= 1 removed since shininess is now
// 1.0 by default (uses matdefs default vals)
#ifdef LOW_QUALITY
// Blinn-Phong
// Note: preferably, H should be computed in the vertex shader
vec3 H = (viewdir + lightdir) * vec3(0.5);
return pow(max(tangDot(H, norm), 0.0), shiny);
#elif defined(WARDISO)
// Isotropic Ward
vec3 halfVec = normalize(viewdir + lightdir);
float NdotH = max(0.001, tangDot(norm, halfVec));
float NdotV = max(0.001, tangDot(norm, viewdir));
float NdotL = max(0.001, tangDot(norm, lightdir));
float a = tan(acos(NdotH));
float p = max(shiny/128.0, 0.001);
return NdotL * (1.0 / (4.0*3.14159265*p*p)) * (exp(-(a*a)/(p*p)) / (sqrt(NdotV * NdotL)));
#else
// Standard Phong
vec3 R = reflect(-lightdir, norm);
return pow(max(tangDot(R, viewdir), 0.0), shiny);
#endif
}
vec2 computeLighting(in vec3 wvNorm, in vec3 wvViewDir, in vec3 wvLightDir){
float diffuseFactor = lightComputeDiffuse(wvNorm, wvLightDir, wvViewDir);
float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, wvLightDir, m_Shininess);
#ifdef HQ_ATTENUATION
float att = clamp(1.0 - g_LightPosition.w * length(lightVec), 0.0, 1.0);
#else
float att = vLightDir.w;
#endif
if (m_Shininess <= 1.0) {
specularFactor = 0.0; // should be one instruction on most cards ..
}
specularFactor *= diffuseFactor;
return vec2(diffuseFactor, specularFactor) * vec2(att);
}
#endif #endif
void main(){ void main(){
@ -172,39 +106,12 @@ void main(){
#ifdef ALPHAMAP #ifdef ALPHAMAP
alpha = alpha * texture2D(m_AlphaMap, newTexCoord).r; alpha = alpha * texture2D(m_AlphaMap, newTexCoord).r;
#endif #endif
#ifdef DISCARD_ALPHA
if(alpha < m_AlphaDiscardThreshold){ if(alpha < m_AlphaDiscardThreshold){
discard; discard;
} }
#ifndef VERTEX_LIGHTING
float spotFallOff = 1.0;
#if __VERSION__ >= 110
// allow use of control flow
if(g_LightDirection.w != 0.0){
#endif #endif
vec3 L = normalize(lightVec.xyz);
vec3 spotdir = normalize(g_LightDirection.xyz);
float curAngleCos = dot(-L, spotdir);
float innerAngleCos = floor(g_LightDirection.w) * 0.001;
float outerAngleCos = fract(g_LightDirection.w);
float innerMinusOuter = innerAngleCos - outerAngleCos;
spotFallOff = (curAngleCos - outerAngleCos) / innerMinusOuter;
#if __VERSION__ >= 110
if(spotFallOff <= 0.0){
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb;
gl_FragColor.a = alpha;
return;
}else{
spotFallOff = clamp(spotFallOff, 0.0, 1.0);
}
}
#else
spotFallOff = clamp(spotFallOff, step(g_LightDirection.w, 0.001), 1.0);
#endif
#endif
// *********************** // ***********************
// Read from textures // Read from textures
@ -257,8 +164,23 @@ void main(){
vec4 lightDir = vLightDir; vec4 lightDir = vLightDir;
lightDir.xyz = normalize(lightDir.xyz); lightDir.xyz = normalize(lightDir.xyz);
vec3 viewDir = normalize(vViewDir); vec3 viewDir = normalize(vViewDir);
float spotFallOff = 1.0;
vec2 light = computeLighting(normal, viewDir, lightDir.xyz) * spotFallOff; #if __VERSION__ >= 110
// allow use of control flow
if(g_LightDirection.w != 0.0){
#endif
spotFallOff = computeSpotFalloff(g_LightDirection, lightVec);
#if __VERSION__ >= 110
if(spotFallOff <= 0.0){
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb;
gl_FragColor.a = alpha;
return;
}
}
#endif
vec2 light = computeLighting(normal, viewDir, lightDir.xyz, lightDir.w * spotFallOff, m_Shininess) ;
#ifdef COLORRAMP #ifdef COLORRAMP
diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb; diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb; specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;

View File

@ -6,34 +6,12 @@ MaterialDef Phong Lighting {
// For better performance // For better performance
Boolean VertexLighting Boolean VertexLighting
// Use more efficent algorithms to improve performance
Boolean LowQuality
// Improve quality at the cost of performance
Boolean HighQuality
// Output alpha from the diffuse map
Boolean UseAlpha
// Alpha threshold for fragment discarding // Alpha threshold for fragment discarding
Float AlphaDiscardThreshold (AlphaTestFallOff) Float AlphaDiscardThreshold (AlphaTestFallOff)
// Normal map is in BC5/ATI2n/LATC/3Dc compression format
Boolean LATC
// Use the provided ambient, diffuse, and specular colors // Use the provided ambient, diffuse, and specular colors
Boolean UseMaterialColors Boolean UseMaterialColors
// Activate shading along the tangent, instead of the normal
// Requires tangent data to be available on the model.
Boolean VTangent
// Use minnaert diffuse instead of lambert
Boolean Minnaert
// Use ward specular instead of phong
Boolean WardIso
// Use vertex color as an additional diffuse color. // Use vertex color as an additional diffuse color.
Boolean UseVertexColor Boolean UseVertexColor
@ -133,9 +111,48 @@ MaterialDef Phong Lighting {
Int NumberOfBones Int NumberOfBones
Matrix4Array BoneMatrices Matrix4Array BoneMatrices
//For instancing
Boolean UseInstancing Boolean UseInstancing
} }
Technique {
LightMode SinglePass
VertexShader GLSL100: Common/MatDefs/Light/SPLighting.vert
FragmentShader GLSL100: Common/MatDefs/Light/SPLighting.frag
WorldParameters {
WorldViewProjectionMatrix
NormalMatrix
WorldViewMatrix
ViewMatrix
CameraPosition
WorldMatrix
ViewProjectionMatrix
}
Defines {
VERTEX_COLOR : UseVertexColor
VERTEX_LIGHTING : VertexLighting
MATERIAL_COLORS : UseMaterialColors
DIFFUSEMAP : DiffuseMap
NORMALMAP : NormalMap
SPECULARMAP : SpecularMap
PARALLAXMAP : ParallaxMap
NORMALMAP_PARALLAX : PackedNormalParallax
STEEP_PARALLAX : SteepParallax
ALPHAMAP : AlphaMap
COLORRAMP : ColorRamp
LIGHTMAP : LightMap
SEPARATE_TEXCOORD : SeparateTexCoord
DISCARD_ALPHA : AlphaDiscardThreshold
USE_REFLECTION : EnvMap
SPHERE_MAP : SphereMap
NUM_BONES : NumberOfBones
INSTANCING : UseInstancing
}
}
Technique { Technique {
LightMode MultiPass LightMode MultiPass
@ -154,17 +171,9 @@ MaterialDef Phong Lighting {
} }
Defines { Defines {
LATC : LATC
VERTEX_COLOR : UseVertexColor VERTEX_COLOR : UseVertexColor
VERTEX_LIGHTING : VertexLighting VERTEX_LIGHTING : VertexLighting
ATTENUATION : Attenuation
MATERIAL_COLORS : UseMaterialColors MATERIAL_COLORS : UseMaterialColors
V_TANGENT : VTangent
MINNAERT : Minnaert
WARDISO : WardIso
LOW_QUALITY : LowQuality
HQ_ATTENUATION : HighQuality
DIFFUSEMAP : DiffuseMap DIFFUSEMAP : DiffuseMap
NORMALMAP : NormalMap NORMALMAP : NormalMap
SPECULARMAP : SpecularMap SPECULARMAP : SpecularMap
@ -175,16 +184,16 @@ MaterialDef Phong Lighting {
COLORRAMP : ColorRamp COLORRAMP : ColorRamp
LIGHTMAP : LightMap LIGHTMAP : LightMap
SEPARATE_TEXCOORD : SeparateTexCoord SEPARATE_TEXCOORD : SeparateTexCoord
DISCARD_ALPHA : AlphaDiscardThreshold
USE_REFLECTION : EnvMap USE_REFLECTION : EnvMap
SPHERE_MAP : SphereMap SPHERE_MAP : SphereMap
NUM_BONES : NumberOfBones NUM_BONES : NumberOfBones
INSTANCING : UseInstancing INSTANCING : UseInstancing
} }
} }
Technique PreShadow { Technique PreShadow {
VertexShader GLSL100 : Common/MatDefs/Shadow/PreShadow.vert VertexShader GLSL100 : Common/MatDefs/Shadow/PreShadow.vert

View File

@ -1,8 +1,10 @@
#import "Common/ShaderLib/Instancing.glsllib" #import "Common/ShaderLib/Instancing.glsllib"
#define ATTENUATION
//#define HQ_ATTENUATION
#import "Common/ShaderLib/Skinning.glsllib" #import "Common/ShaderLib/Skinning.glsllib"
#import "Common/ShaderLib/Lighting.glsllib"
#ifdef VERTEX_LIGHTING
#import "Common/ShaderLib/PhongLighting.glsllib"
#endif
uniform vec4 m_Ambient; uniform vec4 m_Ambient;
uniform vec4 m_Diffuse; uniform vec4 m_Diffuse;
@ -28,7 +30,6 @@ attribute vec2 inTexCoord;
attribute vec3 inNormal; attribute vec3 inNormal;
varying vec3 lightVec; varying vec3 lightVec;
//varying vec4 spotVec;
#ifdef VERTEX_COLOR #ifdef VERTEX_COLOR
attribute vec4 inColor; attribute vec4 inColor;
@ -40,7 +41,6 @@ varying vec3 lightVec;
#ifndef NORMALMAP #ifndef NORMALMAP
varying vec3 vNormal; varying vec3 vNormal;
#endif #endif
//varying vec3 vPosition;
varying vec3 vViewDir; varying vec3 vViewDir;
varying vec4 vLightDir; varying vec4 vLightDir;
#else #else
@ -77,57 +77,6 @@ varying vec3 lightVec;
} }
#endif #endif
// JME3 lights in world space
void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){
float posLight = step(0.5, color.w);
vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
lightVec = tempVec;
#ifdef ATTENUATION
float dist = length(tempVec);
lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
lightDir.xyz = tempVec / vec3(dist);
#else
lightDir = vec4(normalize(tempVec), 1.0);
#endif
}
#ifdef VERTEX_LIGHTING
float lightComputeDiffuse(in vec3 norm, in vec3 lightdir){
return max(0.0, dot(norm, lightdir));
}
float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
if (shiny <= 1.0){
return 0.0;
}
#ifndef LOW_QUALITY
vec3 H = (viewdir + lightdir) * vec3(0.5);
return pow(max(dot(H, norm), 0.0), shiny);
#else
return 0.0;
#endif
}
vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec4 wvLightPos){
vec4 lightDir;
lightComputeDir(wvPos, g_LightColor, wvLightPos, lightDir);
float spotFallOff = 1.0;
if(g_LightDirection.w != 0.0){
vec3 L=normalize(lightVec.xyz);
vec3 spotdir = normalize(g_LightDirection.xyz);
float curAngleCos = dot(-L, spotdir);
float innerAngleCos = floor(g_LightDirection.w) * 0.001;
float outerAngleCos = fract(g_LightDirection.w);
float innerMinusOuter = innerAngleCos - outerAngleCos;
spotFallOff = clamp((curAngleCos - outerAngleCos) / innerMinusOuter, 0.0, 1.0);
}
float diffuseFactor = lightComputeDiffuse(wvNorm, lightDir.xyz);
float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, lightDir.xyz, m_Shininess);
//specularFactor *= step(0.01, diffuseFactor);
return vec2(diffuseFactor, specularFactor) * vec2(lightDir.w)*spotFallOff;
}
#endif
void main(){ void main(){
vec4 modelSpacePos = vec4(inPosition, 1.0); vec4 modelSpacePos = vec4(inPosition, 1.0);
vec3 modelSpaceNorm = inNormal; vec3 modelSpaceNorm = inNormal;
@ -154,11 +103,6 @@ void main(){
vec3 wvNormal = normalize(TransformNormal(modelSpaceNorm));//normalize(g_NormalMatrix * modelSpaceNorm); vec3 wvNormal = normalize(TransformNormal(modelSpaceNorm));//normalize(g_NormalMatrix * modelSpaceNorm);
vec3 viewDir = normalize(-wvPosition); vec3 viewDir = normalize(-wvPosition);
//vec4 lightColor = g_LightColor[gl_InstanceID];
//vec4 lightPos = g_LightPosition[gl_InstanceID];
//vec4 wvLightPos = (g_ViewMatrix * vec4(lightPos.xyz, lightColor.w));
//wvLightPos.w = lightPos.w;
vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz,clamp(g_LightColor.w,0.0,1.0))); vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz,clamp(g_LightColor.w,0.0,1.0)));
wvLightPos.w = g_LightPosition.w; wvLightPos.w = g_LightPosition.w;
vec4 lightColor = g_LightColor; vec4 lightColor = g_LightColor;
@ -166,41 +110,24 @@ void main(){
#if defined(NORMALMAP) && !defined(VERTEX_LIGHTING) #if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
vec3 wvTangent = normalize(TransformNormal(modelSpaceTan)); vec3 wvTangent = normalize(TransformNormal(modelSpaceTan));
vec3 wvBinormal = cross(wvNormal, wvTangent); vec3 wvBinormal = cross(wvNormal, wvTangent);
mat3 tbnMat = mat3(wvTangent, wvBinormal * inTangent.w,wvNormal); mat3 tbnMat = mat3(wvTangent, wvBinormal * inTangent.w,wvNormal);
//vPosition = wvPosition * tbnMat;
//vViewDir = viewDir * tbnMat;
vViewDir = -wvPosition * tbnMat; vViewDir = -wvPosition * tbnMat;
lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir); lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz; vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz;
#elif !defined(VERTEX_LIGHTING) #elif !defined(VERTEX_LIGHTING)
vNormal = wvNormal; vNormal = wvNormal;
//vPosition = wvPosition;
vViewDir = viewDir; vViewDir = viewDir;
lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir);
#ifdef V_TANGENT
vNormal = normalize(TransformNormal(inTangent.xyz));
vNormal = -cross(cross(vLightDir.xyz, vNormal), vNormal);
#endif
#endif #endif
//computing spot direction in view space and unpacking spotlight cos
// spotVec = (g_ViewMatrix * vec4(g_LightDirection.xyz, 0.0) );
// spotVec.w = floor(g_LightDirection.w) * 0.001;
// lightVec.w = fract(g_LightDirection.w);
lightColor.w = 1.0;
#ifdef MATERIAL_COLORS #ifdef MATERIAL_COLORS
AmbientSum = (m_Ambient * g_AmbientLightColor).rgb; AmbientSum = (m_Ambient * g_AmbientLightColor).rgb;
DiffuseSum = m_Diffuse * lightColor; DiffuseSum = m_Diffuse * vec4(lightColor.rgb, 1.0);
SpecularSum = (m_Specular * lightColor).rgb; SpecularSum = (m_Specular * lightColor).rgb;
#else #else
AmbientSum = vec3(0.2, 0.2, 0.2) * g_AmbientLightColor.rgb; // Default: ambient color is dark gray AmbientSum = g_AmbientLightColor.rgb; // Default: ambient color is dark gray
DiffuseSum = lightColor; DiffuseSum = vec4(lightColor.rgb, 1.0);
SpecularSum = vec3(0.0); SpecularSum = vec3(0.0);
#endif #endif
@ -210,7 +137,19 @@ void main(){
#endif #endif
#ifdef VERTEX_LIGHTING #ifdef VERTEX_LIGHTING
vertexLightValues = computeLighting(wvPosition, wvNormal, viewDir, wvLightPos); float spotFallOff = 1.0;
vec4 vLightDir;
lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
#if __VERSION__ >= 110
// allow use of control flow
if(lightColor.w > 1.0){
#endif
spotFallOff = computeSpotFalloff(g_LightDirection, lightVec);
#if __VERSION__ >= 110
}
#endif
vertexLightValues = computeLighting(wvNormal, viewDir, vLightDir.xyz, vLightDir.w * spotFallOff, m_Shininess);
#endif #endif
#ifdef USE_REFLECTION #ifdef USE_REFLECTION

View File

@ -0,0 +1,218 @@
#import "Common/ShaderLib/Parallax.glsllib"
#import "Common/ShaderLib/Optics.glsllib"
#ifndef VERTEX_LIGHTING
#import "Common/ShaderLib/PhongLighting.glsllib"
#import "Common/ShaderLib/Lighting.glsllib"
#endif
varying vec2 texCoord;
#ifdef SEPARATE_TEXCOORD
varying vec2 texCoord2;
#endif
varying vec3 AmbientSum;
varying vec4 DiffuseSum;
varying vec3 SpecularSum;
#ifndef VERTEX_LIGHTING
uniform mat4 g_ViewMatrix;
uniform vec4 g_LightData[NB_LIGHTS];
varying vec3 vPos;
#else
varying vec3 specularAccum;
varying vec4 diffuseAccum;
#endif
#ifdef DIFFUSEMAP
uniform sampler2D m_DiffuseMap;
#endif
#ifdef SPECULARMAP
uniform sampler2D m_SpecularMap;
#endif
#ifdef PARALLAXMAP
uniform sampler2D m_ParallaxMap;
#endif
#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING)
uniform float m_ParallaxHeight;
#endif
#ifdef LIGHTMAP
uniform sampler2D m_LightMap;
#endif
#ifdef NORMALMAP
uniform sampler2D m_NormalMap;
varying vec3 vTangent;
varying vec3 vBinormal;
#endif
varying vec3 vNormal;
#ifdef ALPHAMAP
uniform sampler2D m_AlphaMap;
#endif
#ifdef COLORRAMP
uniform sampler2D m_ColorRamp;
#endif
uniform float m_AlphaDiscardThreshold;
#ifndef VERTEX_LIGHTING
uniform float m_Shininess;
#ifdef USE_REFLECTION
uniform float m_ReflectionPower;
uniform float m_ReflectionIntensity;
varying vec4 refVec;
uniform ENVMAP m_EnvMap;
#endif
#endif
void main(){
vec2 newTexCoord;
#if (defined(PARALLAXMAP) || (defined(NORMALMAP_PARALLAX) && defined(NORMALMAP))) && !defined(VERTEX_LIGHTING)
#ifdef STEEP_PARALLAX
#ifdef NORMALMAP_PARALLAX
//parallax map is stored in the alpha channel of the normal map
newTexCoord = steepParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
#else
//parallax map is a texture
newTexCoord = steepParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);
#endif
#else
#ifdef NORMALMAP_PARALLAX
//parallax map is stored in the alpha channel of the normal map
newTexCoord = classicParallaxOffset(m_NormalMap, vViewDir, texCoord, m_ParallaxHeight);
#else
//parallax map is a texture
newTexCoord = classicParallaxOffset(m_ParallaxMap, vViewDir, texCoord, m_ParallaxHeight);
#endif
#endif
#else
newTexCoord = texCoord;
#endif
#ifdef DIFFUSEMAP
vec4 diffuseColor = texture2D(m_DiffuseMap, newTexCoord);
#else
vec4 diffuseColor = vec4(1.0);
#endif
float alpha = DiffuseSum.a * diffuseColor.a;
#ifdef ALPHAMAP
alpha = alpha * texture2D(m_AlphaMap, newTexCoord).r;
#endif
#ifdef DISCARD_ALPHA
if(alpha < m_AlphaDiscardThreshold){
discard;
}
#endif
// ***********************
// Read from textures
// ***********************
#if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
vec4 normalHeight = texture2D(m_NormalMap, newTexCoord);
//Note the -2.0 and -1.0. We invert the green channel of the normal map,
//as it's complient with normal maps generated with blender.
//see http://hub.jmonkeyengine.org/forum/topic/parallax-mapping-fundamental-bug/#post-256898
//for more explanation.
vec3 normal = normalize((normalHeight.xyz * vec3(2.0,-2.0,2.0) - vec3(1.0,-1.0,1.0)));
#elif !defined(VERTEX_LIGHTING)
vec3 normal = normalize(vNormal);
#endif
#ifdef SPECULARMAP
vec4 specularColor = texture2D(m_SpecularMap, newTexCoord);
#else
vec4 specularColor = vec4(1.0);
#endif
#ifdef LIGHTMAP
vec3 lightMapColor;
#ifdef SEPARATE_TEXCOORD
lightMapColor = texture2D(m_LightMap, texCoord2).rgb;
#else
lightMapColor = texture2D(m_LightMap, texCoord).rgb;
#endif
specularColor.rgb *= lightMapColor;
diffuseColor.rgb *= lightMapColor;
#endif
#ifdef VERTEX_LIGHTING
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb
+diffuseAccum.rgb *diffuseColor.rgb
+specularAccum.rgb * specularColor.rgb;
gl_FragColor.a=1.0;
#else
int i = 0;
gl_FragColor.rgb = AmbientSum * diffuseColor.rgb;
#ifdef USE_REFLECTION
vec4 refColor = Optics_GetEnvColor(m_EnvMap, refVec.xyz);
#endif
#ifdef NORMALMAP
mat3 tbnMat = mat3(normalize(vTangent.xyz) , normalize(vBinormal.xyz) , normalize(vNormal.xyz));
#endif
for( int i = 0;i < NB_LIGHTS; i+=3){
vec4 lightColor = g_LightData[i];
vec4 lightData1 = g_LightData[i+1];
vec4 lightDir;
vec3 lightVec;
lightComputeDir(vPos, lightColor.w, lightData1, lightDir,lightVec);
float spotFallOff = 1.0;
#if __VERSION__ >= 110
// allow use of control flow
if(lightColor.w > 1.0){
#endif
spotFallOff = computeSpotFalloff(g_LightData[i+2], lightVec);
#if __VERSION__ >= 110
}
#endif
#ifdef NORMALMAP
//Normal map -> lighting is computed in tangent space
lightDir.xyz = normalize(lightDir.xyz * tbnMat);
vec3 viewDir = normalize(-vPos.xyz * tbnMat);
#else
//no Normal map -> lighting is computed in view space
lightDir.xyz = normalize(lightDir.xyz);
vec3 viewDir = normalize(-vPos.xyz);
#endif
vec2 light = computeLighting(normal, viewDir, lightDir.xyz, lightDir.w * spotFallOff , m_Shininess);
#ifdef COLORRAMP
diffuseColor.rgb *= texture2D(m_ColorRamp, vec2(light.x, 0.0)).rgb;
specularColor.rgb *= texture2D(m_ColorRamp, vec2(light.y, 0.0)).rgb;
#endif
// Workaround, since it is not possible to modify varying variables
vec4 SpecularSum2 = vec4(SpecularSum, 1.0);
#ifdef USE_REFLECTION
// Interpolate light specularity toward reflection color
// Multiply result by specular map
specularColor = mix(SpecularSum2 * light.y, refColor, refVec.w) * specularColor;
SpecularSum2 = vec4(1.0);
light.y = 1.0;
#endif
gl_FragColor.rgb += DiffuseSum.rgb * lightColor.rgb * diffuseColor.rgb * vec3(light.x) +
SpecularSum2.rgb * specularColor.rgb * vec3(light.y);
}
#endif
gl_FragColor.a = alpha;
}

View File

@ -0,0 +1,172 @@
#import "Common/ShaderLib/Instancing.glsllib"
#import "Common/ShaderLib/Skinning.glsllib"
#import "Common/ShaderLib/Lighting.glsllib"
#ifdef VERTEX_LIGHTING
#import "Common/ShaderLib/PhongLighting.glsllib"
#endif
uniform vec4 m_Ambient;
uniform vec4 m_Diffuse;
uniform vec4 m_Specular;
uniform float m_Shininess;
#if defined(VERTEX_LIGHTING)
uniform vec4 g_LightData[NB_LIGHTS];
#endif
uniform vec4 g_AmbientLightColor;
varying vec2 texCoord;
#ifdef SEPARATE_TEXCOORD
varying vec2 texCoord2;
attribute vec2 inTexCoord2;
#endif
varying vec3 AmbientSum;
varying vec4 DiffuseSum;
varying vec3 SpecularSum;
attribute vec3 inPosition;
attribute vec2 inTexCoord;
attribute vec3 inNormal;
#ifdef VERTEX_COLOR
attribute vec4 inColor;
#endif
#ifndef VERTEX_LIGHTING
varying vec3 vNormal;
varying vec3 vPos;
#ifdef NORMALMAP
attribute vec4 inTangent;
varying vec3 vTangent;
varying vec3 vBinormal;
#endif
#else
varying vec3 specularAccum;
varying vec4 diffuseAccum;
#endif
#ifdef USE_REFLECTION
uniform vec3 g_CameraPosition;
uniform vec3 m_FresnelParams;
varying vec4 refVec;
/**
* Input:
* attribute inPosition
* attribute inNormal
* uniform g_WorldMatrix
* uniform g_CameraPosition
*
* Output:
* varying refVec
*/
void computeRef(in vec4 modelSpacePos){
// vec3 worldPos = (g_WorldMatrix * modelSpacePos).xyz;
vec3 worldPos = TransformWorld(modelSpacePos).xyz;
vec3 I = normalize( g_CameraPosition - worldPos ).xyz;
// vec3 N = normalize( (g_WorldMatrix * vec4(inNormal, 0.0)).xyz );
vec3 N = normalize( TransformWorld(vec4(inNormal, 0.0)).xyz );
refVec.xyz = reflect(I, N);
refVec.w = m_FresnelParams.x + m_FresnelParams.y * pow(1.0 + dot(I, N), m_FresnelParams.z);
}
#endif
void main(){
vec4 modelSpacePos = vec4(inPosition, 1.0);
vec3 modelSpaceNorm = inNormal;
#if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
vec3 modelSpaceTan = inTangent.xyz;
#endif
#ifdef NUM_BONES
#if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
Skinning_Compute(modelSpacePos, modelSpaceNorm, modelSpaceTan);
#else
Skinning_Compute(modelSpacePos, modelSpaceNorm);
#endif
#endif
gl_Position = TransformWorldViewProjection(modelSpacePos);
texCoord = inTexCoord;
#ifdef SEPARATE_TEXCOORD
texCoord2 = inTexCoord2;
#endif
vec3 wvPosition = TransformWorldView(modelSpacePos).xyz;
vec3 wvNormal = normalize(TransformNormal(modelSpaceNorm));
vec3 viewDir = normalize(-wvPosition);
#if defined(NORMALMAP) && !defined(VERTEX_LIGHTING)
vTangent = TransformNormal(modelSpaceTan);
vBinormal = cross(wvNormal, vTangent)* inTangent.w;
vNormal = wvNormal;
vPos = wvPosition;
#elif !defined(VERTEX_LIGHTING)
vNormal = wvNormal;
vPos = wvPosition;
#endif
#ifdef MATERIAL_COLORS
AmbientSum = m_Ambient.rgb * g_AmbientLightColor.rgb;
SpecularSum = m_Specular.rgb;
DiffuseSum = m_Diffuse;
#else
AmbientSum = g_AmbientLightColor.rgb;
SpecularSum = vec3(0.0);
DiffuseSum = vec4(1.0);
#endif
#ifdef VERTEX_COLOR
AmbientSum *= inColor.rgb;
DiffuseSum *= inColor;
#endif
#ifdef VERTEX_LIGHTING
int i = 0;
diffuseAccum = vec4(0.0);
specularAccum = vec3(0.0);
vec4 diffuseColor;
vec3 specularColor;
for (int i =0;i < NB_LIGHTS; i+=3){
vec4 lightColor = g_LightData[i];
vec4 lightData1 = g_LightData[i+1];
DiffuseSum = vec4(1.0);
#ifdef MATERIAL_COLORS
diffuseColor = m_Diffuse * vec4(lightColor.rgb, 1.0);
specularColor = m_Specular.rgb * lightColor.rgb;
#else
diffuseColor = vec4(lightColor.rgb, 1.0);
specularColor = vec3(0.0);
#endif
vec4 lightDir;
vec3 lightVec;
lightComputeDir(wvPosition, lightColor.w, lightData1, lightDir, lightVec);
// lightDir = normalize(lightDir);
// lightVec = normalize(lightVec);
float spotFallOff = 1.0;
#if __VERSION__ >= 110
// allow use of control flow
if(lightColor.w > 1.0){
#endif
vec4 lightDirection = g_LightData[i+2];
spotFallOff = computeSpotFalloff(lightDirection, lightVec);
#if __VERSION__ >= 110
}
#endif
vec2 v = computeLighting(wvNormal, viewDir, lightDir.xyz, lightDir.w * spotFallOff, m_Shininess);
diffuseAccum +=v.x * diffuseColor;
specularAccum += v.y * specularColor;
}
#endif
#ifdef USE_REFLECTION
computeRef(modelSpacePos);
#endif
}

View File

@ -1,48 +1,30 @@
#ifndef NUM_LIGHTS /*Common function for light calculations*/
#define NUM_LIGHTS 4
#endif
uniform mat4 g_ViewMatrix;
uniform vec4 g_LightPosition[NUM_LIGHTS];
uniform vec4 g_g_LightColor[NUM_LIGHTS];
uniform float m_Shininess;
float Lighting_Diffuse(vec3 norm, vec3 lightdir){ /*
return max(0.0, dot(norm, lightdir)); * Computes light direction
} * lightType should be 0.0,1.0,2.0, repectively for Directional, point and spot lights.
* Outputs the light direction and the light half vector.
float Lighting_Specular(vec3 norm, vec3 viewdir, vec3 lightdir, float shiny){ */
vec3 refdir = reflect(-lightdir, norm); void lightComputeDir(in vec3 worldPos, in float ligthType, in vec4 position, out vec4 lightDir, out vec3 lightVec){
return pow(max(dot(refdir, viewdir), 0.0), shiny); float posLight = step(0.5, ligthType);
}
void Lighting_Direction(vec3 worldPos, vec4 color, vec4 position, out vec4 lightDir){
float posLight = step(0.5, color.w);
vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight); vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
lightVec = tempVec;
float dist = length(tempVec); float dist = length(tempVec);
lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0); lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
lightDir.xyz = tempVec / dist; lightDir.xyz = tempVec / vec3(dist);
} }
void Lighting_ComputePS(vec3 tanNormal, mat3 tbnMat, /*
int lightCount, out vec3 outDiffuse, out vec3 outSpecular){ * Computes the spot falloff for a spotlight
// find tangent view dir & vert pos */
vec3 tanViewDir = viewDir * tbnMat; float computeSpotFalloff(in vec4 lightDirection, in vec3 lightVector){
vec3 L=normalize(lightVector);
for (int i = 0; i < lightCount; i++){ vec3 spotdir = normalize(lightDirection.xyz);
// find light dir in tangent space, works for point & directional lights float curAngleCos = dot(-L, spotdir);
vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition[i].xyz, g_LightColor[i].w)); float innerAngleCos = floor(lightDirection.w) * 0.001;
wvLightPos.w = g_LightPosition[i].w; float outerAngleCos = fract(lightDirection.w);
float innerMinusOuter = innerAngleCos - outerAngleCos;
vec4 tanLightDir; return clamp((curAngleCos - outerAngleCos) / innerMinusOuter, step(lightDirection.w, 0.001), 1.0);
Lighting_Direction(wvPosition, g_LightColor[i], wvLightPos, tanLightDir);
tanLightDir.xyz = tanLightDir.xyz * tbnMat;
vec3 lightScale = g_LightColor[i].rgb * tanLightDir.w;
float specular = Lighting_Specular(tanNormal, tanViewDir, tanLightDir.xyz, m_Shininess);
float diffuse = Lighting_Diffuse(tanNormal, tanLightDir.xyz);
outSpecular += specular * lightScale * step(0.01, diffuse) * g_LightColor[i].rgb;
outDiffuse += diffuse * lightScale * g_LightColor[i].rgb;
}
} }

View File

@ -0,0 +1,29 @@
/*Standard Phong ligting*/
/*
* Computes diffuse factor
*/
float lightComputeDiffuse(in vec3 norm, in vec3 lightdir){
return max(0.0, dot(norm, lightdir));
}
/*
* Computes specular factor
*/
float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
vec3 R = reflect(-lightdir, norm);
return pow(max(dot(R, viewdir), 0.0), shiny);
}
/*
* Computes diffuse and specular factors and pack them in a vec2 (x=diffuse, y=specular)
*/
vec2 computeLighting(in vec3 norm, in vec3 viewDir, in vec3 lightDir, in float attenuation, in float shininess){
float diffuseFactor = lightComputeDiffuse(norm, lightDir);
float specularFactor = lightComputeSpecular(norm, viewDir, lightDir, shininess);
if (shininess <= 1.0) {
specularFactor = 0.0; // should be one instruction on most cards ..
}
specularFactor *= diffuseFactor;
return vec2(diffuseFactor, specularFactor) * vec2(attenuation);
}

View File

@ -0,0 +1,255 @@
/*
* Copyright (c) 2009-2012 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jme3test.light;
import com.jme3.app.BasicProfilerState;
import com.jme3.app.SimpleApplication;
import com.jme3.font.BitmapText;
import com.jme3.input.KeyInput;
import com.jme3.input.controls.ActionListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.light.AmbientLight;
import com.jme3.light.DirectionalLight;
import com.jme3.light.Light;
import com.jme3.light.LightList;
import com.jme3.light.PointLight;
import com.jme3.light.SpotLight;
import com.jme3.material.Material;
import com.jme3.material.TechniqueDef;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Geometry;
import com.jme3.scene.LightNode;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import com.jme3.scene.shape.Box;
public class TestManyLightsSingle extends SimpleApplication {
public static void main(String[] args) {
TestManyLightsSingle app = new TestManyLightsSingle();
app.start();
}
TechniqueDef.LightMode lm = TechniqueDef.LightMode.MultiPass;
int lightNum = 6 ;
@Override
public void simpleInitApp() {
renderManager.setPreferredLightMode(lm);
renderManager.setSinglePassLightBatchSize(lightNum);
flyCam.setMoveSpeed(10);
Node scene = (Node) assetManager.loadModel("Scenes/ManyLights/Main.scene");
rootNode.attachChild(scene);
Node n = (Node) rootNode.getChild(0);
LightList lightList = n.getWorldLightList();
Geometry g = (Geometry) n.getChild("Grid-geom-1");
g.getMaterial().setColor("Ambient", new ColorRGBA(0.2f, 0.2f, 0.2f, 1f));
/* A colored lit cube. Needs light source! */
Box boxMesh = new Box(1f, 1f, 1f);
Geometry boxGeo = new Geometry("Colored Box", boxMesh);
Material boxMat = g.getMaterial().clone();
boxMat.setBoolean("UseMaterialColors", true);
boxMat.setColor("Ambient", new ColorRGBA(0.2f, 0.2f, 0.2f, 1f));
boxMat.setColor("Diffuse", ColorRGBA.Blue);
boxGeo.setMaterial(boxMat);
int nb = 0;
for (Light light : lightList) {
nb++;
PointLight p = (PointLight) light;
if (nb >60) {
n.removeLight(light);
} else {
LightNode ln = new LightNode("l", light);
n.attachChild(ln);
ln.setLocalTranslation(p.getPosition());
int rand = FastMath.nextRandomInt(0, 3);
switch (rand) {
case 0:
light.setColor(ColorRGBA.Red);
// ln.addControl(new MoveControl(5f));
break;
case 1:
light.setColor(ColorRGBA.Yellow);
// ln.addControl(new MoveControl(5f));
break;
case 2:
light.setColor(ColorRGBA.Green);
//ln.addControl(new MoveControl(-5f));
break;
case 3:
light.setColor(ColorRGBA.Orange);
//ln.addControl(new MoveControl(-5f));
break;
}
}
Geometry b = boxGeo.clone();
n.attachChild(b);
b.setLocalTranslation(p.getPosition().x, 2, p.getPosition().z);
}
// cam.setLocation(new Vector3f(3.1893547f, 17.977385f, 30.8378f));
// cam.setRotation(new Quaternion(0.14317635f, 0.82302624f, -0.23777823f, 0.49557027f));
cam.setLocation(new Vector3f(-1.8901939f, 29.34097f, 73.07533f));
cam.setRotation(new Quaternion(0.0021000702f, 0.971012f, -0.23886925f, 0.008527749f));
BasicProfilerState profiler = new BasicProfilerState(true);
profiler.setGraphScale(1000f);
// getStateManager().attach(profiler);
// guiNode.setCullHint(CullHint.Always);
flyCam.setDragToRotate(true);
flyCam.setMoveSpeed(50);
inputManager.addListener(new ActionListener() {
public void onAction(String name, boolean isPressed, float tpf) {
if (name.equals("toggle") && isPressed) {
if (lm == TechniqueDef.LightMode.SinglePass) {
lm = TechniqueDef.LightMode.MultiPass;
} else {
lm = TechniqueDef.LightMode.SinglePass;
}
renderManager.setPreferredLightMode(lm);
}
if (name.equals("lightsUp") && isPressed) {
lightNum++;
renderManager.setSinglePassLightBatchSize(lightNum);
helloText.setText("nb lights per batch : " + lightNum);
}
if (name.equals("lightsDown") && isPressed) {
lightNum--;
renderManager.setSinglePassLightBatchSize(lightNum);
helloText.setText("nb lights per batch : " + lightNum);
}
}
}, "toggle", "lightsUp", "lightsDown");
inputManager.addMapping("toggle", new KeyTrigger(KeyInput.KEY_SPACE));
inputManager.addMapping("lightsUp", new KeyTrigger(KeyInput.KEY_UP));
inputManager.addMapping("lightsDown", new KeyTrigger(KeyInput.KEY_DOWN));
SpotLight spot = new SpotLight();
spot.setDirection(new Vector3f(-1f, -1f, -1f).normalizeLocal());
spot.setColor(ColorRGBA.Blue.mult(5));
spot.setSpotOuterAngle(FastMath.DEG_TO_RAD * 20);
spot.setSpotInnerAngle(FastMath.DEG_TO_RAD * 5);
spot.setPosition(new Vector3f(10, 10, 20));
rootNode.addLight(spot);
DirectionalLight dl = new DirectionalLight();
dl.setDirection(new Vector3f(-1, -1, 1));
rootNode.addLight(dl);
AmbientLight al = new AmbientLight();
al.setColor(new ColorRGBA(0.2f, 0.2f, 0.2f, 1f));
rootNode.addLight(al);
/**
* Write text on the screen (HUD)
*/
guiNode.detachAllChildren();
guiFont = assetManager.loadFont("Interface/Fonts/Default.fnt");
helloText = new BitmapText(guiFont, false);
helloText.setSize(guiFont.getCharSet().getRenderedSize());
helloText.setText("nb lights per batch : " + lightNum);
helloText.setLocalTranslation(300, helloText.getLineHeight(), 0);
guiNode.attachChild(helloText);
}
BitmapText helloText;
long time;
long nbFrames;
long startTime = 0;
@Override
public void simpleUpdate(float tpf) {
// if (nbFrames == 4000) {
// startTime = System.nanoTime();
// }
// if (nbFrames > 4000) {
// time = System.nanoTime();
// float average = ((float) time - (float) startTime) / ((float) nbFrames - 4000f);
// helloText.setText("Average = " + average);
// }
// nbFrames++;
}
class MoveControl extends AbstractControl {
float direction;
Vector3f origPos = new Vector3f();
public MoveControl(float direction) {
this.direction = direction;
}
@Override
public void setSpatial(Spatial spatial) {
super.setSpatial(spatial); //To change body of generated methods, choose Tools | Templates.
origPos.set(spatial.getLocalTranslation());
}
float time = 0;
@Override
protected void controlUpdate(float tpf) {
time += tpf;
spatial.setLocalTranslation(origPos.x + FastMath.cos(time) * direction, origPos.y, origPos.z + FastMath.sin(time) * direction);
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
}
}
}

View File

@ -802,7 +802,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
TextureUtil.uploadTexture(img, target, i, 0, tdc); TextureUtil.uploadTexture(img, target, i, 0, tdc);
} }
} else {*/ } else {*/
TextureUtil.uploadTexture(ctxCaps, img, target, 0, 0, false); TextureUtil.uploadTexture(caps, img, target, 0, 0, false);
//} //}
img.clearUpdateNeeded(); img.clearUpdateNeeded();
@ -853,7 +853,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
public void modifyTexture(Texture tex, Image pixels, int x, int y) { public void modifyTexture(Texture tex, Image pixels, int x, int y) {
setTexture(0, tex); setTexture(0, tex);
TextureUtil.uploadSubTexture(ctxCaps, pixels, convertTextureType(tex.getType()), 0, x, y, false); TextureUtil.uploadSubTexture(caps, pixels, convertTextureType(tex.getType()), 0, x, y, false);
} }
private void clearTextureUnits() { private void clearTextureUnits() {

View File

@ -57,7 +57,9 @@ import com.jme3.util.BufferUtils;
import com.jme3.util.ListMap; import com.jme3.util.ListMap;
import com.jme3.util.NativeObjectManager; import com.jme3.util.NativeObjectManager;
import java.nio.*; import java.nio.*;
import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -70,7 +72,6 @@ import static org.lwjgl.opengl.ARBInstancedArrays.*;
import static org.lwjgl.opengl.ARBMultisample.*; import static org.lwjgl.opengl.ARBMultisample.*;
import static org.lwjgl.opengl.ARBTextureMultisample.*; import static org.lwjgl.opengl.ARBTextureMultisample.*;
import static org.lwjgl.opengl.ARBVertexArrayObject.*; import static org.lwjgl.opengl.ARBVertexArrayObject.*;
import org.lwjgl.opengl.ContextCapabilities;
import static org.lwjgl.opengl.EXTFramebufferBlit.*; import static org.lwjgl.opengl.EXTFramebufferBlit.*;
import static org.lwjgl.opengl.EXTFramebufferMultisample.*; import static org.lwjgl.opengl.EXTFramebufferMultisample.*;
import static org.lwjgl.opengl.EXTFramebufferObject.*; import static org.lwjgl.opengl.EXTFramebufferObject.*;
@ -84,7 +85,7 @@ import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL14.*; import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL15.*; import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*; import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.opengl.GLContext; import org.lwjgl.opengl.GL30;
//import static org.lwjgl.opengl.GL21.*; //import static org.lwjgl.opengl.GL21.*;
//import static org.lwjgl.opengl.GL30.*; //import static org.lwjgl.opengl.GL30.*;
@ -101,10 +102,7 @@ public class LwjglRenderer implements Renderer {
private final RenderContext context = new RenderContext(); private final RenderContext context = new RenderContext();
private final NativeObjectManager objManager = new NativeObjectManager(); private final NativeObjectManager objManager = new NativeObjectManager();
private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class); private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
// current state
private Shader boundShader;
private int initialDrawBuf, initialReadBuf;
private int glslVer;
private int vertexTextureUnits; private int vertexTextureUnits;
private int fragTextureUnits; private int fragTextureUnits;
private int vertexUniforms; private int vertexUniforms;
@ -120,13 +118,12 @@ public class LwjglRenderer implements Renderer {
private int maxTriCount; private int maxTriCount;
private int maxColorTexSamples; private int maxColorTexSamples;
private int maxDepthTexSamples; private int maxDepthTexSamples;
private FrameBuffer lastFb = null;
private FrameBuffer mainFbOverride = null; private FrameBuffer mainFbOverride = null;
private final Statistics statistics = new Statistics(); private final Statistics statistics = new Statistics();
private int vpX, vpY, vpW, vpH; private int vpX, vpY, vpW, vpH;
private int clipX, clipY, clipW, clipH; private int clipX, clipY, clipW, clipH;
private boolean linearizeSrgbImages; private boolean linearizeSrgbImages;
private ContextCapabilities ctxCaps; private HashSet<String> extensions;
public LwjglRenderer() { public LwjglRenderer() {
} }
@ -153,18 +150,67 @@ public class LwjglRenderer implements Renderer {
return caps; return caps;
} }
@SuppressWarnings("fallthrough") private static HashSet<String> loadExtensions(String extensions) {
public void initialize() { HashSet<String> extensionSet = new HashSet<String>(64);
ctxCaps = GLContext.getCapabilities(); for (String extension : extensions.split(" ")) {
if (ctxCaps.OpenGL20) { extensionSet.add(extension);
}
return extensionSet;
}
private static int extractVersion(String prefixStr, String versionStr) {
if (versionStr != null) {
int spaceIdx = versionStr.indexOf(" ", prefixStr.length());
if (spaceIdx >= 1) {
versionStr = versionStr.substring(prefixStr.length(), spaceIdx).trim();
} else {
versionStr = versionStr.substring(prefixStr.length()).trim();
}
// Some device have ":" at the end of the version.
versionStr = versionStr.replaceAll("\\:", "");
// Pivot on first point.
int firstPoint = versionStr.indexOf(".");
// Remove everything after second point.
int secondPoint = versionStr.indexOf(".", firstPoint + 1);
if (secondPoint != -1) {
versionStr = versionStr.substring(0, secondPoint);
}
String majorVerStr = versionStr.substring(0, firstPoint);
String minorVerStr = versionStr.substring(firstPoint + 1);
if (minorVerStr.endsWith("0") && minorVerStr.length() > 1) {
minorVerStr = minorVerStr.substring(0, minorVerStr.length() - 1);
}
int majorVer = Integer.parseInt(majorVerStr);
int minorVer = Integer.parseInt(minorVerStr);
return majorVer * 100 + minorVer * 10;
} else {
return -1;
}
}
private boolean hasExtension(String extensionName) {
return extensions.contains(extensionName);
}
private void loadCapabilities() {
int oglVer = extractVersion("", glGetString(GL_VERSION));
if (oglVer >= 200) {
caps.add(Caps.OpenGL20); caps.add(Caps.OpenGL20);
if (ctxCaps.OpenGL21) { if (oglVer >= 210) {
caps.add(Caps.OpenGL21); caps.add(Caps.OpenGL21);
if (ctxCaps.OpenGL30) { if (oglVer >= 300) {
caps.add(Caps.OpenGL30); caps.add(Caps.OpenGL30);
if (ctxCaps.OpenGL31) { if (oglVer >= 310) {
caps.add(Caps.OpenGL31); caps.add(Caps.OpenGL31);
if (ctxCaps.OpenGL32) { if (oglVer >= 320) {
caps.add(Caps.OpenGL32); caps.add(Caps.OpenGL32);
} }
} }
@ -172,48 +218,14 @@ public class LwjglRenderer implements Renderer {
} }
} }
//workaround, always assume we support GLSL100 int glslVer = extractVersion("", glGetString(GL_SHADING_LANGUAGE_VERSION));
//some cards just don't report this correctly
caps.add(Caps.GLSL100);
String versionStr = null;
if (ctxCaps.OpenGL20) {
versionStr = glGetString(GL_SHADING_LANGUAGE_VERSION);
}
if (versionStr == null || versionStr.equals("")) {
glslVer = -1;
throw new UnsupportedOperationException("GLSL and OpenGL2 is "
+ "required for the LWJGL "
+ "renderer!");
}
// Fix issue in TestRenderToMemory when GL_FRONT is the main
// buffer being used.
initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
initialReadBuf = glGetInteger(GL_READ_BUFFER);
// XXX: This has to be GL_BACK for canvas on Mac
// Since initialDrawBuf is GL_FRONT for pbuffer, gotta
// change this value later on ...
// initialDrawBuf = GL_BACK;
// initialReadBuf = GL_BACK;
int spaceIdx = versionStr.indexOf(" ");
if (spaceIdx >= 1) {
versionStr = versionStr.substring(0, spaceIdx);
}
float version = Float.parseFloat(versionStr);
glslVer = (int) (version * 100);
switch (glslVer) { switch (glslVer) {
default: default:
if (glslVer < 400) { if (glslVer < 400) {
break; break;
} }
// so that future OpenGL revisions wont break jme3 // so that future OpenGL revisions wont break jme3
// fall through intentional // fall through intentional
case 400: case 400:
case 330: case 330:
@ -232,11 +244,28 @@ public class LwjglRenderer implements Renderer {
break; break;
} }
if (!caps.contains(Caps.GLSL100)) { // Workaround, always assume we support GLSL100.
logger.log(Level.WARNING, "Force-adding GLSL100 support, since OpenGL2 is supported."); // Some cards just don't report this correctly.
caps.add(Caps.GLSL100); caps.add(Caps.GLSL100);
extensions = loadExtensions(glGetString(GL_EXTENSIONS));
} }
@SuppressWarnings("fallthrough")
public void initialize() {
loadCapabilities();
// Fix issue in TestRenderToMemory when GL_FRONT is the main
// buffer being used.
context.initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
context.initialReadBuf = glGetInteger(GL_READ_BUFFER);
// XXX: This has to be GL_BACK for canvas on Mac
// Since initialDrawBuf is GL_FRONT for pbuffer, gotta
// change this value later on ...
// initialDrawBuf = GL_BACK;
// initialReadBuf = GL_BACK;
glGetInteger(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, intBuf16); glGetInteger(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, intBuf16);
vertexTextureUnits = intBuf16.get(0); vertexTextureUnits = intBuf16.get(0);
logger.log(Level.FINER, "VTF Units: {0}", vertexTextureUnits); logger.log(Level.FINER, "VTF Units: {0}", vertexTextureUnits);
@ -280,44 +309,41 @@ public class LwjglRenderer implements Renderer {
maxCubeTexSize = intBuf16.get(0); maxCubeTexSize = intBuf16.get(0);
logger.log(Level.FINER, "Maximum CubeMap Resolution: {0}", maxCubeTexSize); logger.log(Level.FINER, "Maximum CubeMap Resolution: {0}", maxCubeTexSize);
if (ctxCaps.GL_ARB_color_buffer_float) { // ctxCaps = GLContext.getCapabilities();
if (hasExtension("GL_ARB_color_buffer_float") &&
hasExtension("GL_ARB_half_float_pixel")) {
// XXX: Require both 16 and 32 bit float support for FloatColorBuffer. // XXX: Require both 16 and 32 bit float support for FloatColorBuffer.
if (ctxCaps.GL_ARB_half_float_pixel) {
caps.add(Caps.FloatColorBuffer); caps.add(Caps.FloatColorBuffer);
} }
}
if (ctxCaps.GL_ARB_depth_buffer_float) { if (hasExtension("GL_ARB_depth_buffer_float")) {
caps.add(Caps.FloatDepthBuffer); caps.add(Caps.FloatDepthBuffer);
} }
if (ctxCaps.OpenGL30) { if (caps.contains(Caps.OpenGL30)) {
caps.add(Caps.PackedDepthStencilBuffer); caps.add(Caps.PackedDepthStencilBuffer);
} }
if (ctxCaps.GL_ARB_draw_instanced && ctxCaps.GL_ARB_instanced_arrays) { if (hasExtension("GL_ARB_draw_instanced") &&
hasExtension("GL_ARB_instanced_arrays")) {
caps.add(Caps.MeshInstancing); caps.add(Caps.MeshInstancing);
} }
if (ctxCaps.GL_ARB_fragment_program) { if (hasExtension("GL_ARB_texture_buffer_object")) {
caps.add(Caps.ARBprogram);
}
if (ctxCaps.GL_ARB_texture_buffer_object) {
caps.add(Caps.TextureBuffer); caps.add(Caps.TextureBuffer);
} }
if (ctxCaps.GL_ARB_texture_float) { if (hasExtension("GL_ARB_texture_float") &&
if (ctxCaps.GL_ARB_half_float_pixel) { hasExtension("GL_ARB_half_float_pixel")) {
caps.add(Caps.FloatTexture); caps.add(Caps.FloatTexture);
} }
}
if (ctxCaps.GL_ARB_vertex_array_object) { if (hasExtension("GL_ARB_vertex_array_object") || caps.contains(Caps.OpenGL30)) {
caps.add(Caps.VertexBufferArray); caps.add(Caps.VertexBufferArray);
} }
if (ctxCaps.GL_ARB_texture_non_power_of_two) { if (hasExtension("GL_ARB_texture_non_power_of_two") || caps.contains(Caps.OpenGL30)) {
caps.add(Caps.NonPowerOfTwoTextures); caps.add(Caps.NonPowerOfTwoTextures);
} else { } else {
logger.log(Level.WARNING, "Your graphics card does not " logger.log(Level.WARNING, "Your graphics card does not "
@ -325,30 +351,34 @@ public class LwjglRenderer implements Renderer {
+ "Some features might not work."); + "Some features might not work.");
} }
boolean latc = ctxCaps.GL_EXT_texture_compression_latc; if (hasExtension("GL_EXT_texture_compression_latc")) {
if (latc) {
caps.add(Caps.TextureCompressionLATC); caps.add(Caps.TextureCompressionLATC);
} }
if (ctxCaps.GL_EXT_packed_float || ctxCaps.OpenGL30) { if (hasExtension("GL_EXT_packed_float") || caps.contains(Caps.OpenGL30)) {
// This format is part of the OGL3 specification // This format is part of the OGL3 specification
caps.add(Caps.PackedFloatColorBuffer); caps.add(Caps.PackedFloatColorBuffer);
if (ctxCaps.GL_ARB_half_float_pixel) {
if (hasExtension("GL_ARB_half_float_pixel")) {
// because textures are usually uploaded as RGB16F // because textures are usually uploaded as RGB16F
// need half-float pixel // need half-float pixel
caps.add(Caps.PackedFloatTexture); caps.add(Caps.PackedFloatTexture);
} }
} }
if (ctxCaps.GL_EXT_texture_array || ctxCaps.OpenGL30) { if (hasExtension("GL_EXT_texture_array") || caps.contains(Caps.OpenGL30)) {
caps.add(Caps.TextureArray); caps.add(Caps.TextureArray);
} }
if (ctxCaps.GL_EXT_texture_shared_exponent || ctxCaps.OpenGL30) { if (hasExtension("GL_EXT_texture_shared_exponent") || caps.contains(Caps.OpenGL30)) {
caps.add(Caps.SharedExponentTexture); caps.add(Caps.SharedExponentTexture);
} }
if (ctxCaps.GL_EXT_framebuffer_object) { if (hasExtension("GL_EXT_texture_filter_anisotropic")) {
caps.add(Caps.TextureFilterAnisotropic);
}
if (hasExtension("GL_EXT_framebuffer_object")) {
caps.add(Caps.FrameBuffer); caps.add(Caps.FrameBuffer);
glGetInteger(GL_MAX_RENDERBUFFER_SIZE_EXT, intBuf16); glGetInteger(GL_MAX_RENDERBUFFER_SIZE_EXT, intBuf16);
@ -359,7 +389,7 @@ public class LwjglRenderer implements Renderer {
maxFBOAttachs = intBuf16.get(0); maxFBOAttachs = intBuf16.get(0);
logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs); logger.log(Level.FINER, "FBO Max renderbuffers: {0}", maxFBOAttachs);
if (ctxCaps.GL_EXT_framebuffer_multisample) { if (hasExtension("GL_EXT_framebuffer_multisample")) {
caps.add(Caps.FrameBufferMultisample); caps.add(Caps.FrameBufferMultisample);
glGetInteger(GL_MAX_SAMPLES_EXT, intBuf16); glGetInteger(GL_MAX_SAMPLES_EXT, intBuf16);
@ -367,7 +397,7 @@ public class LwjglRenderer implements Renderer {
logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples); logger.log(Level.FINER, "FBO Max Samples: {0}", maxFBOSamples);
} }
if (ctxCaps.GL_ARB_texture_multisample) { if (hasExtension("GL_ARB_texture_multisample")) {
caps.add(Caps.TextureMultisample); caps.add(Caps.TextureMultisample);
glGetInteger(GL_MAX_COLOR_TEXTURE_SAMPLES, intBuf16); glGetInteger(GL_MAX_COLOR_TEXTURE_SAMPLES, intBuf16);
@ -387,7 +417,7 @@ public class LwjglRenderer implements Renderer {
} }
} }
if (ctxCaps.GL_ARB_multisample) { if (hasExtension("GL_ARB_multisample")) {
glGetInteger(GL_SAMPLE_BUFFERS_ARB, intBuf16); glGetInteger(GL_SAMPLE_BUFFERS_ARB, intBuf16);
boolean available = intBuf16.get(0) != 0; boolean available = intBuf16.get(0) != 0;
glGetInteger(GL_SAMPLES_ARB, intBuf16); glGetInteger(GL_SAMPLES_ARB, intBuf16);
@ -401,7 +431,8 @@ public class LwjglRenderer implements Renderer {
} }
// Supports sRGB pipeline. // Supports sRGB pipeline.
if ( (ctxCaps.GL_ARB_framebuffer_sRGB && ctxCaps.GL_EXT_texture_sRGB ) || ctxCaps.OpenGL30 ) { if ( (hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB"))
|| caps.contains(Caps.OpenGL30) ) {
caps.add(Caps.Srgb); caps.add(Caps.Srgb);
} }
@ -410,11 +441,8 @@ public class LwjglRenderer implements Renderer {
public void invalidateState() { public void invalidateState() {
context.reset(); context.reset();
boundShader = null; context.initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
lastFb = null; context.initialReadBuf = glGetInteger(GL_READ_BUFFER);
initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
initialReadBuf = glGetInteger(GL_READ_BUFFER);
} }
public void resetGLObjects() { public void resetGLObjects() {
@ -479,7 +507,7 @@ public class LwjglRenderer implements Renderer {
} }
public void setAlphaToCoverage(boolean value) { public void setAlphaToCoverage(boolean value) {
if (ctxCaps.GL_ARB_multisample) { if (caps.contains(Caps.Multisample)) {
if (value) { if (value) {
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB); glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);
} else { } else {
@ -822,7 +850,7 @@ public class LwjglRenderer implements Renderer {
if (context.boundShaderProgram != shaderId) { if (context.boundShaderProgram != shaderId) {
glUseProgram(shaderId); glUseProgram(shaderId);
statistics.onShaderUse(shader, true); statistics.onShaderUse(shader, true);
boundShader = shader; context.boundShader = shader;
context.boundShaderProgram = shaderId; context.boundShaderProgram = shaderId;
} else { } else {
statistics.onShaderUse(shader, false); statistics.onShaderUse(shader, false);
@ -1081,12 +1109,12 @@ public class LwjglRenderer implements Renderer {
glAttachShader(id, source.getId()); glAttachShader(id, source.getId());
} }
if (ctxCaps.GL_EXT_gpu_shader4) { if (caps.contains(Caps.OpenGL30)) {
// Check if GLSL version is 1.5 for shader // Check if GLSL version is 1.5 for shader
glBindFragDataLocationEXT(id, 0, "outFragColor"); GL30.glBindFragDataLocation(id, 0, "outFragColor");
// For MRT // For MRT
for (int i = 0; i < maxMRTFBOAttachs; i++) { for (int i = 0; i < maxMRTFBOAttachs; i++) {
glBindFragDataLocationEXT(id, i, "outFragData[" + i + "]"); GL30.glBindFragDataLocation(id, i, "outFragData[" + i + "]");
} }
} }
@ -1191,7 +1219,7 @@ public class LwjglRenderer implements Renderer {
} }
public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) { public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
if (ctxCaps.GL_EXT_framebuffer_blit) { if (caps.contains(Caps.FrameBufferBlit)) {
int srcX0 = 0; int srcX0 = 0;
int srcY0 = 0; int srcY0 = 0;
int srcX1; int srcX1;
@ -1292,11 +1320,11 @@ public class LwjglRenderer implements Renderer {
int attachment = convertAttachmentSlot(rb.getSlot()); int attachment = convertAttachmentSlot(rb.getSlot());
int type = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT, int type = glGetFramebufferAttachmentParameteriEXT(GL_DRAW_FRAMEBUFFER_EXT,
attachment, attachment,
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT); GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT);
int rbName = glGetFramebufferAttachmentParameterEXT(GL_DRAW_FRAMEBUFFER_EXT, int rbName = glGetFramebufferAttachmentParameteriEXT(GL_DRAW_FRAMEBUFFER_EXT,
attachment, attachment,
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT); GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT);
@ -1397,9 +1425,9 @@ public class LwjglRenderer implements Renderer {
+ ":" + fb.getHeight() + " is not supported."); + ":" + fb.getHeight() + " is not supported.");
} }
TextureUtil.GLImageFormat glFmt = TextureUtil.getImageFormatWithError(ctxCaps, rb.getFormat(), fb.isSrgb()); TextureUtil.GLImageFormat glFmt = TextureUtil.getImageFormatWithError(caps, rb.getFormat(), fb.isSrgb());
if (fb.getSamples() > 1 && ctxCaps.GL_EXT_framebuffer_multisample) { if (fb.getSamples() > 1 && caps.contains(Caps.FrameBufferMultisample)) {
int samples = fb.getSamples(); int samples = fb.getSamples();
if (maxFBOSamples < samples) { if (maxFBOSamples < samples) {
samples = maxFBOSamples; samples = maxFBOSamples;
@ -1503,7 +1531,7 @@ public class LwjglRenderer implements Renderer {
if (fb.getSamples() <= 1) { if (fb.getSamples() <= 1) {
throw new IllegalArgumentException("Framebuffer must be multisampled"); throw new IllegalArgumentException("Framebuffer must be multisampled");
} }
if (!ctxCaps.GL_ARB_texture_multisample) { if (!caps.contains(Caps.TextureMultisample)) {
throw new RendererException("Multisampled textures are not supported"); throw new RendererException("Multisampled textures are not supported");
} }
@ -1525,7 +1553,7 @@ public class LwjglRenderer implements Renderer {
} }
public void setFrameBuffer(FrameBuffer fb) { public void setFrameBuffer(FrameBuffer fb) {
if (!ctxCaps.GL_EXT_framebuffer_object) { if (!caps.contains(Caps.FrameBuffer)) {
throw new RendererException("Framebuffer objects are not supported" + throw new RendererException("Framebuffer objects are not supported" +
" by the video hardware"); " by the video hardware");
} }
@ -1534,16 +1562,16 @@ public class LwjglRenderer implements Renderer {
fb = mainFbOverride; fb = mainFbOverride;
} }
if (lastFb == fb) { if (context.boundFB == fb) {
if (fb == null || !fb.isUpdateNeeded()) { if (fb == null || !fb.isUpdateNeeded()) {
return; return;
} }
} }
// generate mipmaps for last FB if needed // generate mipmaps for last FB if needed
if (lastFb != null) { if (context.boundFB != null) {
for (int i = 0; i < lastFb.getNumColorBuffers(); i++) { for (int i = 0; i < context.boundFB.getNumColorBuffers(); i++) {
RenderBuffer rb = lastFb.getColorBuffer(i); RenderBuffer rb = context.boundFB.getColorBuffer(i);
Texture tex = rb.getTexture(); Texture tex = rb.getTexture();
if (tex != null if (tex != null
&& tex.getMinFilter().usesMipMapLevels()) { && tex.getMinFilter().usesMipMapLevels()) {
@ -1567,15 +1595,15 @@ public class LwjglRenderer implements Renderer {
} }
// select back buffer // select back buffer
if (context.boundDrawBuf != -1) { if (context.boundDrawBuf != -1) {
glDrawBuffer(initialDrawBuf); glDrawBuffer(context.initialDrawBuf);
context.boundDrawBuf = -1; context.boundDrawBuf = -1;
} }
if (context.boundReadBuf != -1) { if (context.boundReadBuf != -1) {
glReadBuffer(initialReadBuf); glReadBuffer(context.initialReadBuf);
context.boundReadBuf = -1; context.boundReadBuf = -1;
} }
lastFb = null; context.boundFB = null;
} else { } else {
if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) { if (fb.getNumColorBuffers() == 0 && fb.getDepthBuffer() == null) {
throw new IllegalArgumentException("The framebuffer: " + fb throw new IllegalArgumentException("The framebuffer: " + fb
@ -1644,7 +1672,7 @@ public class LwjglRenderer implements Renderer {
assert fb.getId() >= 0; assert fb.getId() >= 0;
assert context.boundFBO == fb.getId(); assert context.boundFBO == fb.getId();
lastFb = fb; context.boundFB = fb;
try { try {
checkFrameBufferError(); checkFrameBufferError();
@ -1707,7 +1735,7 @@ public class LwjglRenderer implements Renderer {
|* Textures *| |* Textures *|
\*********************************************************************/ \*********************************************************************/
private int convertTextureType(Texture.Type type, int samples, int face) { private int convertTextureType(Texture.Type type, int samples, int face) {
if (samples > 1 && !ctxCaps.GL_ARB_texture_multisample) { if (samples > 1 && !caps.contains(Caps.TextureMultisample)) {
throw new RendererException("Multisample textures are not supported" + throw new RendererException("Multisample textures are not supported" +
" by the video hardware."); " by the video hardware.");
} }
@ -1751,7 +1779,8 @@ public class LwjglRenderer implements Renderer {
} }
} }
private int convertMinFilter(Texture.MinFilter filter) { private int convertMinFilter(Texture.MinFilter filter, boolean haveMips) {
if (haveMips){
switch (filter) { switch (filter) {
case Trilinear: case Trilinear:
return GL_LINEAR_MIPMAP_LINEAR; return GL_LINEAR_MIPMAP_LINEAR;
@ -1768,6 +1797,20 @@ public class LwjglRenderer implements Renderer {
default: default:
throw new UnsupportedOperationException("Unknown min filter: " + filter); throw new UnsupportedOperationException("Unknown min filter: " + filter);
} }
} else {
switch (filter) {
case Trilinear:
case BilinearNearestMipMap:
case BilinearNoMipMaps:
return GL_LINEAR;
case NearestLinearMipMap:
case NearestNearestMipMap:
case NearestNoMipMaps:
return GL_NEAREST;
default:
throw new UnsupportedOperationException("Unknown min filter: " + filter);
}
}
} }
private int convertWrapMode(Texture.WrapMode mode) { private int convertWrapMode(Texture.WrapMode mode) {
@ -1792,14 +1835,20 @@ public class LwjglRenderer implements Renderer {
Image image = tex.getImage(); Image image = tex.getImage();
int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1); int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1);
boolean haveMips = true;
if (image != null) {
haveMips = image.isGeneratedMipmapsRequired() || image.hasMipmaps();
}
// filter things // filter things
int minFilter = convertMinFilter(tex.getMinFilter()); int minFilter = convertMinFilter(tex.getMinFilter(), haveMips);
int magFilter = convertMagFilter(tex.getMagFilter()); int magFilter = convertMagFilter(tex.getMagFilter());
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilter); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilter); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilter);
if (tex.getAnisotropicFilter() > 1) { if (tex.getAnisotropicFilter() > 1) {
if (ctxCaps.GL_EXT_texture_filter_anisotropic) { if (caps.contains(Caps.TextureFilterAnisotropic)) {
glTexParameterf(target, glTexParameterf(target,
GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_TEXTURE_MAX_ANISOTROPY_EXT,
tex.getAnisotropicFilter()); tex.getAnisotropicFilter());
@ -1881,7 +1930,7 @@ public class LwjglRenderer implements Renderer {
// Image does not have mipmaps, but they are required. // Image does not have mipmaps, but they are required.
// Generate from base level. // Generate from base level.
if (!ctxCaps.OpenGL30) { if (!caps.contains(Caps.OpenGL30)) {
glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE);
img.setMipmapsGenerated(true); img.setMipmapsGenerated(true);
} else { } else {
@ -1908,7 +1957,7 @@ public class LwjglRenderer implements Renderer {
} }
// Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT. // Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT.
if (!ctxCaps.GL_ARB_texture_non_power_of_two && img.isNPOT()) { if (!caps.contains(Caps.NonPowerOfTwoTextures) && img.isNPOT()) {
if (img.getData(0) == null) { if (img.getData(0) == null) {
throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware"); throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware");
} else { } else {
@ -1917,7 +1966,7 @@ public class LwjglRenderer implements Renderer {
} }
// Check if graphics card doesn't support multisample textures // Check if graphics card doesn't support multisample textures
if (!ctxCaps.GL_ARB_texture_multisample) { if (!caps.contains(Caps.TextureMultisample)) {
if (img.getMultiSamples() > 1) { if (img.getMultiSamples() > 1) {
throw new RendererException("Multisample textures not supported by graphics hardware"); throw new RendererException("Multisample textures not supported by graphics hardware");
} }
@ -1928,6 +1977,9 @@ public class LwjglRenderer implements Renderer {
if (img.getWidth() > maxCubeTexSize || img.getHeight() > maxCubeTexSize) { if (img.getWidth() > maxCubeTexSize || img.getHeight() > maxCubeTexSize) {
throw new RendererException("Cannot upload cubemap " + img + ". The maximum supported cubemap resolution is " + maxCubeTexSize); throw new RendererException("Cannot upload cubemap " + img + ". The maximum supported cubemap resolution is " + maxCubeTexSize);
} }
if (img.getWidth() != img.getHeight()) {
throw new RendererException("Cubemaps must have square dimensions");
}
} else { } else {
if (img.getWidth() > maxTexSize || img.getHeight() > maxTexSize) { if (img.getWidth() > maxTexSize || img.getHeight() > maxTexSize) {
throw new RendererException("Cannot upload texture " + img + ". The maximum supported texture resolution is " + maxTexSize); throw new RendererException("Cannot upload texture " + img + ". The maximum supported texture resolution is " + maxTexSize);
@ -1942,7 +1994,7 @@ public class LwjglRenderer implements Renderer {
return; return;
} }
for (int i = 0; i < 6; i++) { for (int i = 0; i < 6; i++) {
TextureUtil.uploadTexture(ctxCaps, img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, linearizeSrgbImages); TextureUtil.uploadTexture(caps, img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, linearizeSrgbImages);
} }
} else if (target == GL_TEXTURE_2D_ARRAY_EXT) { } else if (target == GL_TEXTURE_2D_ARRAY_EXT) {
if (!caps.contains(Caps.TextureArray)) { if (!caps.contains(Caps.TextureArray)) {
@ -1952,22 +2004,22 @@ public class LwjglRenderer implements Renderer {
List<ByteBuffer> data = img.getData(); List<ByteBuffer> data = img.getData();
// -1 index specifies prepare data for 2D Array // -1 index specifies prepare data for 2D Array
TextureUtil.uploadTexture(ctxCaps, img, target, -1, 0, linearizeSrgbImages); TextureUtil.uploadTexture(caps, img, target, -1, 0, linearizeSrgbImages);
for (int i = 0; i < data.size(); i++) { for (int i = 0; i < data.size(); i++) {
// upload each slice of 2D array in turn // upload each slice of 2D array in turn
// this time with the appropriate index // this time with the appropriate index
TextureUtil.uploadTexture(ctxCaps, img, target, i, 0, linearizeSrgbImages); TextureUtil.uploadTexture(caps, img, target, i, 0, linearizeSrgbImages);
} }
} else { } else {
TextureUtil.uploadTexture(ctxCaps, img, target, 0, 0, linearizeSrgbImages); TextureUtil.uploadTexture(caps, img, target, 0, 0, linearizeSrgbImages);
} }
if (img.getMultiSamples() != imageSamples) { if (img.getMultiSamples() != imageSamples) {
img.setMultiSamples(imageSamples); img.setMultiSamples(imageSamples);
} }
if (ctxCaps.OpenGL30) { if (caps.contains(Caps.OpenGL30)) {
if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired() && img.getData() != null) { if (!img.hasMipmaps() && img.isGeneratedMipmapsRequired() && img.getData() != null) {
// XXX: Required for ATI // XXX: Required for ATI
glEnable(target); glEnable(target);
@ -2018,7 +2070,7 @@ public class LwjglRenderer implements Renderer {
public void modifyTexture(Texture tex, Image pixels, int x, int y) { public void modifyTexture(Texture tex, Image pixels, int x, int y) {
setTexture(0, tex); setTexture(0, tex);
TextureUtil.uploadSubTexture(ctxCaps, pixels, convertTextureType(tex.getType(), pixels.getMultiSamples(), -1), 0, x, y, linearizeSrgbImages); TextureUtil.uploadSubTexture(caps, pixels, convertTextureType(tex.getType(), pixels.getMultiSamples(), -1), 0, x, y, linearizeSrgbImages);
} }
public void clearTextureUnits() { public void clearTextureUnits() {
@ -2213,8 +2265,9 @@ public class LwjglRenderer implements Renderer {
} }
int programId = context.boundShaderProgram; int programId = context.boundShaderProgram;
if (programId > 0) { if (programId > 0) {
Attribute attrib = boundShader.getAttribute(vb.getBufferType()); Attribute attrib = context.boundShader.getAttribute(vb.getBufferType());
int loc = attrib.getLocation(); int loc = attrib.getLocation();
if (loc == -1) { if (loc == -1) {
return; // not defined return; // not defined
@ -2236,8 +2289,7 @@ public class LwjglRenderer implements Renderer {
} }
if (vb.isInstanced()) { if (vb.isInstanced()) {
if (!ctxCaps.GL_ARB_instanced_arrays if (!caps.contains(Caps.MeshInstancing)) {
|| !ctxCaps.GL_ARB_draw_instanced) {
throw new RendererException("Instancing is required, " throw new RendererException("Instancing is required, "
+ "but not supported by the " + "but not supported by the "
+ "graphics hardware"); + "graphics hardware");

View File

@ -32,11 +32,13 @@
package com.jme3.renderer.lwjgl; package com.jme3.renderer.lwjgl;
import com.jme3.renderer.Caps;
import com.jme3.renderer.RendererException; import com.jme3.renderer.RendererException;
import com.jme3.texture.Image; import com.jme3.texture.Image;
import com.jme3.texture.Image.Format; import com.jme3.texture.Image.Format;
import com.jme3.texture.image.ColorSpace; import com.jme3.texture.image.ColorSpace;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.EnumSet;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import static org.lwjgl.opengl.ARBDepthBufferFloat.*; import static org.lwjgl.opengl.ARBDepthBufferFloat.*;
@ -55,7 +57,6 @@ import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL12.*; import static org.lwjgl.opengl.GL12.*;
import static org.lwjgl.opengl.GL13.*; import static org.lwjgl.opengl.GL13.*;
import static org.lwjgl.opengl.GL14.*; import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL20.*;
class TextureUtil { class TextureUtil {
@ -157,18 +158,18 @@ class TextureUtil {
private static final GLImageFormat sRGB_DXT3 = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true); private static final GLImageFormat sRGB_DXT3 = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
private static final GLImageFormat sRGB_DXT5 = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true); private static final GLImageFormat sRGB_DXT5 = new GLImageFormat(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, GL_UNSIGNED_BYTE, true);
public static GLImageFormat getImageFormat(ContextCapabilities caps, Format fmt, boolean isSrgb){ public static GLImageFormat getImageFormat(EnumSet<Caps> caps, Format fmt, boolean isSrgb){
switch (fmt){ switch (fmt){
case DXT1: case DXT1:
case DXT1A: case DXT1A:
case DXT3: case DXT3:
case DXT5: case DXT5:
if (!caps.GL_EXT_texture_compression_s3tc) { if (!caps.contains(Caps.TextureCompressionS3TC)) {
return null; return null;
} }
break; break;
case Depth24Stencil8: case Depth24Stencil8:
if (!caps.OpenGL30 && !caps.GL_EXT_packed_depth_stencil){ if (!caps.contains(Caps.PackedDepthStencilBuffer)){
return null; return null;
} }
break; break;
@ -179,30 +180,30 @@ class TextureUtil {
case RGB32F: case RGB32F:
case RGBA16F: case RGBA16F:
case RGBA32F: case RGBA32F:
if (!caps.OpenGL30 && !caps.GL_ARB_texture_float){ if (!caps.contains(Caps.FloatTexture)){
return null; return null;
} }
break; break;
case Depth32F: case Depth32F:
if (!caps.OpenGL30 && !caps.GL_NV_depth_buffer_float){ if (!caps.contains(Caps.FloatDepthBuffer)){
return null; return null;
} }
break; break;
case LATC: case LATC:
case LTC: case LTC:
if (!caps.GL_EXT_texture_compression_latc){ if (!caps.contains(Caps.TextureCompressionLATC)){
return null; return null;
} }
break; break;
case RGB9E5: case RGB9E5:
case RGB16F_to_RGB9E5: case RGB16F_to_RGB9E5:
if (!caps.OpenGL30 && !caps.GL_EXT_texture_shared_exponent){ if (!caps.contains(Caps.SharedExponentTexture)){
return null; return null;
} }
break; break;
case RGB111110F: case RGB111110F:
case RGB16F_to_RGB111110F: case RGB16F_to_RGB111110F:
if (!caps.OpenGL30 && !caps.GL_EXT_packed_float){ if (!caps.contains(Caps.PackedFloatTexture)){
return null; return null;
} }
break; break;
@ -214,7 +215,7 @@ class TextureUtil {
} }
} }
public static GLImageFormat getImageFormatWithError(ContextCapabilities caps, Format fmt, boolean isSrgb) { public static GLImageFormat getImageFormatWithError(EnumSet<Caps> caps, Format fmt, boolean isSrgb) {
GLImageFormat glFmt = getImageFormat(caps, fmt, isSrgb); GLImageFormat glFmt = getImageFormat(caps, fmt, isSrgb);
if (glFmt == null) { if (glFmt == null) {
throw new RendererException("Image format '" + fmt + "' is unsupported by the video hardware."); throw new RendererException("Image format '" + fmt + "' is unsupported by the video hardware.");
@ -254,7 +255,7 @@ class TextureUtil {
} }
} }
public static void uploadTexture(ContextCapabilities caps, public static void uploadTexture(EnumSet<Caps> caps,
Image image, Image image,
int target, int target,
int index, int index,
@ -412,7 +413,7 @@ class TextureUtil {
* @param y the y position where to put the image in the texture * @param y the y position where to put the image in the texture
*/ */
public static void uploadSubTexture( public static void uploadSubTexture(
ContextCapabilities caps, EnumSet<Caps> caps,
Image image, Image image,
int target, int target,
int index, int index,

View File

@ -0,0 +1,615 @@
#import "Common/ShaderLib/PhongLighting.glsllib"
#import "Common/ShaderLib/Lighting.glsllib"
uniform float m_Shininess;
varying vec4 AmbientSum;
varying vec4 DiffuseSum;
varying vec4 SpecularSum;
uniform mat4 g_ViewMatrix;
uniform vec4 g_LightData[NB_LIGHTS];
varying vec3 vTangent;
varying vec3 vBinormal;
varying vec3 vPos;
varying vec3 vNormal;
varying vec2 texCoord;
#ifdef DIFFUSEMAP
uniform sampler2D m_DiffuseMap;
#endif
#ifdef DIFFUSEMAP_1
uniform sampler2D m_DiffuseMap_1;
#endif
#ifdef DIFFUSEMAP_2
uniform sampler2D m_DiffuseMap_2;
#endif
#ifdef DIFFUSEMAP_3
uniform sampler2D m_DiffuseMap_3;
#endif
#ifdef DIFFUSEMAP_4
uniform sampler2D m_DiffuseMap_4;
#endif
#ifdef DIFFUSEMAP_5
uniform sampler2D m_DiffuseMap_5;
#endif
#ifdef DIFFUSEMAP_6
uniform sampler2D m_DiffuseMap_6;
#endif
#ifdef DIFFUSEMAP_7
uniform sampler2D m_DiffuseMap_7;
#endif
#ifdef DIFFUSEMAP_8
uniform sampler2D m_DiffuseMap_8;
#endif
#ifdef DIFFUSEMAP_9
uniform sampler2D m_DiffuseMap_9;
#endif
#ifdef DIFFUSEMAP_10
uniform sampler2D m_DiffuseMap_10;
#endif
#ifdef DIFFUSEMAP_11
uniform sampler2D m_DiffuseMap_11;
#endif
#ifdef DIFFUSEMAP_0_SCALE
uniform float m_DiffuseMap_0_scale;
#endif
#ifdef DIFFUSEMAP_1_SCALE
uniform float m_DiffuseMap_1_scale;
#endif
#ifdef DIFFUSEMAP_2_SCALE
uniform float m_DiffuseMap_2_scale;
#endif
#ifdef DIFFUSEMAP_3_SCALE
uniform float m_DiffuseMap_3_scale;
#endif
#ifdef DIFFUSEMAP_4_SCALE
uniform float m_DiffuseMap_4_scale;
#endif
#ifdef DIFFUSEMAP_5_SCALE
uniform float m_DiffuseMap_5_scale;
#endif
#ifdef DIFFUSEMAP_6_SCALE
uniform float m_DiffuseMap_6_scale;
#endif
#ifdef DIFFUSEMAP_7_SCALE
uniform float m_DiffuseMap_7_scale;
#endif
#ifdef DIFFUSEMAP_8_SCALE
uniform float m_DiffuseMap_8_scale;
#endif
#ifdef DIFFUSEMAP_9_SCALE
uniform float m_DiffuseMap_9_scale;
#endif
#ifdef DIFFUSEMAP_10_SCALE
uniform float m_DiffuseMap_10_scale;
#endif
#ifdef DIFFUSEMAP_11_SCALE
uniform float m_DiffuseMap_11_scale;
#endif
#ifdef ALPHAMAP
uniform sampler2D m_AlphaMap;
#endif
#ifdef ALPHAMAP_1
uniform sampler2D m_AlphaMap_1;
#endif
#ifdef ALPHAMAP_2
uniform sampler2D m_AlphaMap_2;
#endif
#ifdef NORMALMAP
uniform sampler2D m_NormalMap;
#endif
#ifdef NORMALMAP_1
uniform sampler2D m_NormalMap_1;
#endif
#ifdef NORMALMAP_2
uniform sampler2D m_NormalMap_2;
#endif
#ifdef NORMALMAP_3
uniform sampler2D m_NormalMap_3;
#endif
#ifdef NORMALMAP_4
uniform sampler2D m_NormalMap_4;
#endif
#ifdef NORMALMAP_5
uniform sampler2D m_NormalMap_5;
#endif
#ifdef NORMALMAP_6
uniform sampler2D m_NormalMap_6;
#endif
#ifdef NORMALMAP_7
uniform sampler2D m_NormalMap_7;
#endif
#ifdef NORMALMAP_8
uniform sampler2D m_NormalMap_8;
#endif
#ifdef NORMALMAP_9
uniform sampler2D m_NormalMap_9;
#endif
#ifdef NORMALMAP_10
uniform sampler2D m_NormalMap_10;
#endif
#ifdef NORMALMAP_11
uniform sampler2D m_NormalMap_11;
#endif
#ifdef TRI_PLANAR_MAPPING
varying vec4 wVertex;
varying vec3 wNormal;
#endif
#ifdef ALPHAMAP
vec4 calculateDiffuseBlend(in vec2 texCoord) {
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
#endif
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
vec4 diffuseColor = texture2D(m_DiffuseMap, texCoord * m_DiffuseMap_0_scale);
diffuseColor *= alphaBlend.r;
#ifdef DIFFUSEMAP_1
vec4 diffuseColor1 = texture2D(m_DiffuseMap_1, texCoord * m_DiffuseMap_1_scale);
diffuseColor = mix( diffuseColor, diffuseColor1, alphaBlend.g );
#endif
#ifdef DIFFUSEMAP_2
vec4 diffuseColor2 = texture2D(m_DiffuseMap_2, texCoord * m_DiffuseMap_2_scale);
diffuseColor = mix( diffuseColor, diffuseColor2, alphaBlend.b );
#endif
#ifdef DIFFUSEMAP_3
vec4 diffuseColor3 = texture2D(m_DiffuseMap_3, texCoord * m_DiffuseMap_3_scale);
diffuseColor = mix( diffuseColor, diffuseColor3, alphaBlend.a );
#endif
#ifdef ALPHAMAP_1
#ifdef DIFFUSEMAP_4
vec4 diffuseColor4 = texture2D(m_DiffuseMap_4, texCoord * m_DiffuseMap_4_scale);
diffuseColor = mix( diffuseColor, diffuseColor4, alphaBlend1.r );
#endif
#ifdef DIFFUSEMAP_5
vec4 diffuseColor5 = texture2D(m_DiffuseMap_5, texCoord * m_DiffuseMap_5_scale);
diffuseColor = mix( diffuseColor, diffuseColor5, alphaBlend1.g );
#endif
#ifdef DIFFUSEMAP_6
vec4 diffuseColor6 = texture2D(m_DiffuseMap_6, texCoord * m_DiffuseMap_6_scale);
diffuseColor = mix( diffuseColor, diffuseColor6, alphaBlend1.b );
#endif
#ifdef DIFFUSEMAP_7
vec4 diffuseColor7 = texture2D(m_DiffuseMap_7, texCoord * m_DiffuseMap_7_scale);
diffuseColor = mix( diffuseColor, diffuseColor7, alphaBlend1.a );
#endif
#endif
#ifdef ALPHAMAP_2
#ifdef DIFFUSEMAP_8
vec4 diffuseColor8 = texture2D(m_DiffuseMap_8, texCoord * m_DiffuseMap_8_scale);
diffuseColor = mix( diffuseColor, diffuseColor8, alphaBlend2.r );
#endif
#ifdef DIFFUSEMAP_9
vec4 diffuseColor9 = texture2D(m_DiffuseMap_9, texCoord * m_DiffuseMap_9_scale);
diffuseColor = mix( diffuseColor, diffuseColor9, alphaBlend2.g );
#endif
#ifdef DIFFUSEMAP_10
vec4 diffuseColor10 = texture2D(m_DiffuseMap_10, texCoord * m_DiffuseMap_10_scale);
diffuseColor = mix( diffuseColor, diffuseColor10, alphaBlend2.b );
#endif
#ifdef DIFFUSEMAP_11
vec4 diffuseColor11 = texture2D(m_DiffuseMap_11, texCoord * m_DiffuseMap_11_scale);
diffuseColor = mix( diffuseColor, diffuseColor11, alphaBlend2.a );
#endif
#endif
return diffuseColor;
}
vec3 calculateNormal(in vec2 texCoord) {
vec3 normal = vec3(0,0,1);
vec3 n = vec3(0,0,0);
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
#endif
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
#ifdef NORMALMAP
n = texture2D(m_NormalMap, texCoord * m_DiffuseMap_0_scale).xyz;
normal += n * alphaBlend.r;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.r;
#endif
#ifdef NORMALMAP_1
n = texture2D(m_NormalMap_1, texCoord * m_DiffuseMap_1_scale).xyz;
normal += n * alphaBlend.g;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.g;
#endif
#ifdef NORMALMAP_2
n = texture2D(m_NormalMap_2, texCoord * m_DiffuseMap_2_scale).xyz;
normal += n * alphaBlend.b;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.b;
#endif
#ifdef NORMALMAP_3
n = texture2D(m_NormalMap_3, texCoord * m_DiffuseMap_3_scale).xyz;
normal += n * alphaBlend.a;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.a;
#endif
#ifdef ALPHAMAP_1
#ifdef NORMALMAP_4
n = texture2D(m_NormalMap_4, texCoord * m_DiffuseMap_4_scale).xyz;
normal += n * alphaBlend1.r;
#endif
#ifdef NORMALMAP_5
n = texture2D(m_NormalMap_5, texCoord * m_DiffuseMap_5_scale).xyz;
normal += n * alphaBlend1.g;
#endif
#ifdef NORMALMAP_6
n = texture2D(m_NormalMap_6, texCoord * m_DiffuseMap_6_scale).xyz;
normal += n * alphaBlend1.b;
#endif
#ifdef NORMALMAP_7
n = texture2D(m_NormalMap_7, texCoord * m_DiffuseMap_7_scale).xyz;
normal += n * alphaBlend1.a;
#endif
#endif
#ifdef ALPHAMAP_2
#ifdef NORMALMAP_8
n = texture2D(m_NormalMap_8, texCoord * m_DiffuseMap_8_scale).xyz;
normal += n * alphaBlend2.r;
#endif
#ifdef NORMALMAP_9
n = texture2D(m_NormalMap_9, texCoord * m_DiffuseMap_9_scale);
normal += n * alphaBlend2.g;
#endif
#ifdef NORMALMAP_10
n = texture2D(m_NormalMap_10, texCoord * m_DiffuseMap_10_scale);
normal += n * alphaBlend2.b;
#endif
#ifdef NORMALMAP_11
n = texture2D(m_NormalMap_11, texCoord * m_DiffuseMap_11_scale);
normal += n * alphaBlend2.a;
#endif
#endif
normal = (normal.xyz * vec3(2.0) - vec3(1.0));
return normalize(normal);
}
#ifdef TRI_PLANAR_MAPPING
vec4 getTriPlanarBlend(in vec4 coords, in vec3 blending, in sampler2D map, in float scale) {
vec4 col1 = texture2D( map, coords.yz * scale);
vec4 col2 = texture2D( map, coords.xz * scale);
vec4 col3 = texture2D( map, coords.xy * scale);
// blend the results of the 3 planar projections.
vec4 tex = col1 * blending.x + col2 * blending.y + col3 * blending.z;
return tex;
}
vec4 calculateTriPlanarDiffuseBlend(in vec3 wNorm, in vec4 wVert, in vec2 texCoord) {
// tri-planar texture bending factor for this fragment's normal
vec3 blending = abs( wNorm );
blending = (blending -0.2) * 0.7;
blending = normalize(max(blending, 0.00001)); // Force weights to sum to 1.0 (very important!)
float b = (blending.x + blending.y + blending.z);
blending /= vec3(b, b, b);
// texture coords
vec4 coords = wVert;
// blend the results of the 3 planar projections.
vec4 tex0 = getTriPlanarBlend(coords, blending, m_DiffuseMap, m_DiffuseMap_0_scale);
#ifdef DIFFUSEMAP_1
// blend the results of the 3 planar projections.
vec4 tex1 = getTriPlanarBlend(coords, blending, m_DiffuseMap_1, m_DiffuseMap_1_scale);
#endif
#ifdef DIFFUSEMAP_2
// blend the results of the 3 planar projections.
vec4 tex2 = getTriPlanarBlend(coords, blending, m_DiffuseMap_2, m_DiffuseMap_2_scale);
#endif
#ifdef DIFFUSEMAP_3
// blend the results of the 3 planar projections.
vec4 tex3 = getTriPlanarBlend(coords, blending, m_DiffuseMap_3, m_DiffuseMap_3_scale);
#endif
#ifdef DIFFUSEMAP_4
// blend the results of the 3 planar projections.
vec4 tex4 = getTriPlanarBlend(coords, blending, m_DiffuseMap_4, m_DiffuseMap_4_scale);
#endif
#ifdef DIFFUSEMAP_5
// blend the results of the 3 planar projections.
vec4 tex5 = getTriPlanarBlend(coords, blending, m_DiffuseMap_5, m_DiffuseMap_5_scale);
#endif
#ifdef DIFFUSEMAP_6
// blend the results of the 3 planar projections.
vec4 tex6 = getTriPlanarBlend(coords, blending, m_DiffuseMap_6, m_DiffuseMap_6_scale);
#endif
#ifdef DIFFUSEMAP_7
// blend the results of the 3 planar projections.
vec4 tex7 = getTriPlanarBlend(coords, blending, m_DiffuseMap_7, m_DiffuseMap_7_scale);
#endif
#ifdef DIFFUSEMAP_8
// blend the results of the 3 planar projections.
vec4 tex8 = getTriPlanarBlend(coords, blending, m_DiffuseMap_8, m_DiffuseMap_8_scale);
#endif
#ifdef DIFFUSEMAP_9
// blend the results of the 3 planar projections.
vec4 tex9 = getTriPlanarBlend(coords, blending, m_DiffuseMap_9, m_DiffuseMap_9_scale);
#endif
#ifdef DIFFUSEMAP_10
// blend the results of the 3 planar projections.
vec4 tex10 = getTriPlanarBlend(coords, blending, m_DiffuseMap_10, m_DiffuseMap_10_scale);
#endif
#ifdef DIFFUSEMAP_11
// blend the results of the 3 planar projections.
vec4 tex11 = getTriPlanarBlend(coords, blending, m_DiffuseMap_11, m_DiffuseMap_11_scale);
#endif
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
#endif
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
vec4 diffuseColor = tex0 * alphaBlend.r;
#ifdef DIFFUSEMAP_1
diffuseColor = mix( diffuseColor, tex1, alphaBlend.g );
#endif
#ifdef DIFFUSEMAP_2
diffuseColor = mix( diffuseColor, tex2, alphaBlend.b );
#endif
#ifdef DIFFUSEMAP_3
diffuseColor = mix( diffuseColor, tex3, alphaBlend.a );
#endif
#ifdef ALPHAMAP_1
#ifdef DIFFUSEMAP_4
diffuseColor = mix( diffuseColor, tex4, alphaBlend1.r );
#endif
#ifdef DIFFUSEMAP_5
diffuseColor = mix( diffuseColor, tex5, alphaBlend1.g );
#endif
#ifdef DIFFUSEMAP_6
diffuseColor = mix( diffuseColor, tex6, alphaBlend1.b );
#endif
#ifdef DIFFUSEMAP_7
diffuseColor = mix( diffuseColor, tex7, alphaBlend1.a );
#endif
#endif
#ifdef ALPHAMAP_2
#ifdef DIFFUSEMAP_8
diffuseColor = mix( diffuseColor, tex8, alphaBlend2.r );
#endif
#ifdef DIFFUSEMAP_9
diffuseColor = mix( diffuseColor, tex9, alphaBlend2.g );
#endif
#ifdef DIFFUSEMAP_10
diffuseColor = mix( diffuseColor, tex10, alphaBlend2.b );
#endif
#ifdef DIFFUSEMAP_11
diffuseColor = mix( diffuseColor, tex11, alphaBlend2.a );
#endif
#endif
return diffuseColor;
}
vec3 calculateNormalTriPlanar(in vec3 wNorm, in vec4 wVert,in vec2 texCoord) {
// tri-planar texture bending factor for this fragment's world-space normal
vec3 blending = abs( wNorm );
blending = (blending -0.2) * 0.7;
blending = normalize(max(blending, 0.00001)); // Force weights to sum to 1.0 (very important!)
float b = (blending.x + blending.y + blending.z);
blending /= vec3(b, b, b);
// texture coords
vec4 coords = wVert;
vec4 alphaBlend = texture2D( m_AlphaMap, texCoord.xy );
#ifdef ALPHAMAP_1
vec4 alphaBlend1 = texture2D( m_AlphaMap_1, texCoord.xy );
#endif
#ifdef ALPHAMAP_2
vec4 alphaBlend2 = texture2D( m_AlphaMap_2, texCoord.xy );
#endif
vec3 normal = vec3(0,0,1);
vec3 n = vec3(0,0,0);
#ifdef NORMALMAP
n = getTriPlanarBlend(coords, blending, m_NormalMap, m_DiffuseMap_0_scale).xyz;
normal += n * alphaBlend.r;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.r;
#endif
#ifdef NORMALMAP_1
n = getTriPlanarBlend(coords, blending, m_NormalMap_1, m_DiffuseMap_1_scale).xyz;
normal += n * alphaBlend.g;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.g;
#endif
#ifdef NORMALMAP_2
n = getTriPlanarBlend(coords, blending, m_NormalMap_2, m_DiffuseMap_2_scale).xyz;
normal += n * alphaBlend.b;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.b;
#endif
#ifdef NORMALMAP_3
n = getTriPlanarBlend(coords, blending, m_NormalMap_3, m_DiffuseMap_3_scale).xyz;
normal += n * alphaBlend.a;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.a;
#endif
#ifdef ALPHAMAP_1
#ifdef NORMALMAP_4
n = getTriPlanarBlend(coords, blending, m_NormalMap_4, m_DiffuseMap_4_scale).xyz;
normal += n * alphaBlend1.r;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.r;
#endif
#ifdef NORMALMAP_5
n = getTriPlanarBlend(coords, blending, m_NormalMap_5, m_DiffuseMap_5_scale).xyz;
normal += n * alphaBlend1.g;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.g;
#endif
#ifdef NORMALMAP_6
n = getTriPlanarBlend(coords, blending, m_NormalMap_6, m_DiffuseMap_6_scale).xyz;
normal += n * alphaBlend1.b;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.b;
#endif
#ifdef NORMALMAP_7
n = getTriPlanarBlend(coords, blending, m_NormalMap_7, m_DiffuseMap_7_scale).xyz;
normal += n * alphaBlend1.a;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.a;
#endif
#endif
#ifdef ALPHAMAP_2
#ifdef NORMALMAP_8
n = getTriPlanarBlend(coords, blending, m_NormalMap_8, m_DiffuseMap_8_scale).xyz;
normal += n * alphaBlend2.r;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.r;
#endif
#ifdef NORMALMAP_9
n = getTriPlanarBlend(coords, blending, m_NormalMap_9, m_DiffuseMap_9_scale).xyz;
normal += n * alphaBlend2.g;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.g;
#endif
#ifdef NORMALMAP_10
n = getTriPlanarBlend(coords, blending, m_NormalMap_10, m_DiffuseMap_10_scale).xyz;
normal += n * alphaBlend2.b;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.b;
#endif
#ifdef NORMALMAP_11
n = getTriPlanarBlend(coords, blending, m_NormalMap_11, m_DiffuseMap_11_scale).xyz;
normal += n * alphaBlend2.a;
#else
normal += vec3(0.5,0.5,1) * alphaBlend.a;
#endif
#endif
normal = (normal.xyz * vec3(2.0) - vec3(1.0));
return normalize(normal);
}
#endif
#endif
void main(){
//----------------------
// diffuse calculations
//----------------------
#ifdef DIFFUSEMAP
#ifdef ALPHAMAP
#ifdef TRI_PLANAR_MAPPING
vec4 diffuseColor = calculateTriPlanarDiffuseBlend(wNormal, wVertex, texCoord);
#else
vec4 diffuseColor = calculateDiffuseBlend(texCoord);
#endif
#else
vec4 diffuseColor = texture2D(m_DiffuseMap, texCoord);
#endif
#else
vec4 diffuseColor = vec4(1.0);
#endif
//---------------------
// normal calculations
//---------------------
#if defined(NORMALMAP) || defined(NORMALMAP_1) || defined(NORMALMAP_2) || defined(NORMALMAP_3) || defined(NORMALMAP_4) || defined(NORMALMAP_5) || defined(NORMALMAP_6) || defined(NORMALMAP_7) || defined(NORMALMAP_8) || defined(NORMALMAP_9) || defined(NORMALMAP_10) || defined(NORMALMAP_11)
#ifdef TRI_PLANAR_MAPPING
vec3 normal = calculateNormalTriPlanar(wNormal, wVertex, texCoord);
#else
vec3 normal = calculateNormal(texCoord);
#endif
mat3 tbnMat = mat3(normalize(vTangent.xyz) , normalize(vBinormal.xyz) , normalize(vNormal.xyz));
#else
vec3 normal = vNormal;
#endif
//-----------------------
// lighting calculations
//-----------------------
gl_FragColor = AmbientSum * diffuseColor;
for( int i = 0;i < NB_LIGHTS; i+=3){
vec4 lightColor = g_LightData[i];
vec4 lightData1 = g_LightData[i+1];
vec4 lightDir;
vec3 lightVec;
lightComputeDir(vPos, lightColor.w, lightData1, lightDir, lightVec);
float spotFallOff = 1.0;
#if __VERSION__ >= 110
// allow use of control flow
if(lightColor.w > 1.0){
#endif
spotFallOff = computeSpotFalloff(g_LightData[i+2], lightVec);
#if __VERSION__ >= 110
}
#endif
#ifdef NORMALMAP
//Normal map -> lighting is computed in tangent space
lightDir.xyz = normalize(lightDir.xyz * tbnMat);
vec3 viewDir = normalize(-vPos.xyz * tbnMat);
#else
//no Normal map -> lighting is computed in view space
lightDir.xyz = normalize(lightDir.xyz);
vec3 viewDir = normalize(-vPos.xyz);
#endif
vec2 light = computeLighting(normal, viewDir, lightDir.xyz, lightDir.w * spotFallOff, m_Shininess);
gl_FragColor.rgb += DiffuseSum.rgb * lightColor.rgb * diffuseColor.rgb * vec3(light.x) +
SpecularSum.rgb * vec3(light.y);
}
}

View File

@ -0,0 +1,66 @@
uniform mat4 g_WorldViewProjectionMatrix;
uniform mat4 g_WorldViewMatrix;
uniform mat3 g_NormalMatrix;
uniform mat4 g_ViewMatrix;
uniform vec4 g_AmbientLightColor;
attribute vec3 inPosition;
attribute vec3 inNormal;
attribute vec2 inTexCoord;
attribute vec4 inTangent;
varying vec3 vNormal;
varying vec2 texCoord;
varying vec3 vPos;
varying vec3 vTangent;
varying vec3 vBinormal;
varying vec4 AmbientSum;
varying vec4 DiffuseSum;
varying vec4 SpecularSum;
#ifdef TRI_PLANAR_MAPPING
varying vec4 wVertex;
varying vec3 wNormal;
#endif
void main(){
vec4 pos = vec4(inPosition, 1.0);
gl_Position = g_WorldViewProjectionMatrix * pos;
#ifdef TERRAIN_GRID
texCoord = inTexCoord * 2.0;
#else
texCoord = inTexCoord;
#endif
vec3 wvPosition = (g_WorldViewMatrix * pos).xyz;
vec3 wvNormal = normalize(g_NormalMatrix * inNormal);
//--------------------------
// specific to normal maps:
//--------------------------
#if defined(NORMALMAP) || defined(NORMALMAP_1) || defined(NORMALMAP_2) || defined(NORMALMAP_3) || defined(NORMALMAP_4) || defined(NORMALMAP_5) || defined(NORMALMAP_6) || defined(NORMALMAP_7) || defined(NORMALMAP_8) || defined(NORMALMAP_9) || defined(NORMALMAP_10) || defined(NORMALMAP_11)
vTangent = g_NormalMatrix * inTangent.xyz;
vBinormal = cross(wvNormal, vTangent)* inTangent.w;
#endif
//-------------------------
// general to all lighting
//-------------------------
vNormal = wvNormal;
vPos = wvPosition;
AmbientSum = g_AmbientLightColor;
DiffuseSum = vec4(1.0);
SpecularSum = vec4(0.0);
#ifdef TRI_PLANAR_MAPPING
wVertex = vec4(inPosition,0.0);
wNormal = inNormal;
#endif
}

View File

@ -1,3 +1,5 @@
#import "Common/ShaderLib/PhongLighting.glsllib"
#import "Common/ShaderLib/Lighting.glsllib"
uniform float m_Shininess; uniform float m_Shininess;
uniform vec4 g_LightDirection; uniform vec4 g_LightDirection;
@ -145,54 +147,6 @@ varying vec3 lightVec;
varying vec3 wNormal; varying vec3 wNormal;
#endif #endif
float tangDot(in vec3 v1, in vec3 v2){
float d = dot(v1,v2);
#ifdef V_TANGENT
d = 1.0 - d*d;
return step(0.0, d) * sqrt(d);
#else
return d;
#endif
}
float lightComputeDiffuse(in vec3 norm, in vec3 lightdir, in vec3 viewdir){
return max(0.0, dot(norm, lightdir));
}
float lightComputeSpecular(in vec3 norm, in vec3 viewdir, in vec3 lightdir, in float shiny){
#ifdef WARDISO
// Isotropic Ward
vec3 halfVec = normalize(viewdir + lightdir);
float NdotH = max(0.001, tangDot(norm, halfVec));
float NdotV = max(0.001, tangDot(norm, viewdir));
float NdotL = max(0.001, tangDot(norm, lightdir));
float a = tan(acos(NdotH));
float p = max(shiny/128.0, 0.001);
return NdotL * (1.0 / (4.0*3.14159265*p*p)) * (exp(-(a*a)/(p*p)) / (sqrt(NdotV * NdotL)));
#else
// Standard Phong
vec3 R = reflect(-lightdir, norm);
return pow(max(tangDot(R, viewdir), 0.0), shiny);
#endif
}
vec2 computeLighting(in vec3 wvPos, in vec3 wvNorm, in vec3 wvViewDir, in vec3 wvLightDir){
float diffuseFactor = lightComputeDiffuse(wvNorm, wvLightDir, wvViewDir);
float specularFactor = lightComputeSpecular(wvNorm, wvViewDir, wvLightDir, m_Shininess);
if (m_Shininess <= 1.0) {
specularFactor = 0.0; // should be one instruction on most cards ..
}
float att = vLightDir.w;
return vec2(diffuseFactor, specularFactor) * vec2(att);
}
#ifdef ALPHAMAP #ifdef ALPHAMAP
vec4 calculateDiffuseBlend(in vec2 texCoord) { vec4 calculateDiffuseBlend(in vec2 texCoord) {
@ -648,7 +602,7 @@ void main(){
vec4 lightDir = vLightDir; vec4 lightDir = vLightDir;
lightDir.xyz = normalize(lightDir.xyz); lightDir.xyz = normalize(lightDir.xyz);
vec2 light = computeLighting(vPosition, normal, vViewDir.xyz, lightDir.xyz)*spotFallOff; vec2 light = computeLighting(normal, vViewDir.xyz, lightDir.xyz,lightDir.w*spotFallOff,m_Shininess);
vec4 specularColor = vec4(1.0); vec4 specularColor = vec4(1.0);

View File

@ -163,6 +163,70 @@ MaterialDef Terrain Lighting {
} }
} }
Technique {
LightMode SinglePass
VertexShader GLSL100: Common/MatDefs/Terrain/SPTerrainLighting.vert
FragmentShader GLSL100: Common/MatDefs/Terrain/SPTerrainLighting.frag
WorldParameters {
WorldViewProjectionMatrix
NormalMatrix
WorldViewMatrix
ViewMatrix
}
Defines {
TRI_PLANAR_MAPPING : useTriPlanarMapping
TERRAIN_GRID : isTerrainGrid
WARDISO : WardIso
DIFFUSEMAP : DiffuseMap
DIFFUSEMAP_1 : DiffuseMap_1
DIFFUSEMAP_2 : DiffuseMap_2
DIFFUSEMAP_3 : DiffuseMap_3
DIFFUSEMAP_4 : DiffuseMap_4
DIFFUSEMAP_5 : DiffuseMap_5
DIFFUSEMAP_6 : DiffuseMap_6
DIFFUSEMAP_7 : DiffuseMap_7
DIFFUSEMAP_8 : DiffuseMap_8
DIFFUSEMAP_9 : DiffuseMap_9
DIFFUSEMAP_10 : DiffuseMap_10
DIFFUSEMAP_11 : DiffuseMap_11
NORMALMAP : NormalMap
NORMALMAP_1 : NormalMap_1
NORMALMAP_2 : NormalMap_2
NORMALMAP_3 : NormalMap_3
NORMALMAP_4 : NormalMap_4
NORMALMAP_5 : NormalMap_5
NORMALMAP_6 : NormalMap_6
NORMALMAP_7 : NormalMap_7
NORMALMAP_8 : NormalMap_8
NORMALMAP_9 : NormalMap_9
NORMALMAP_10 : NormalMap_10
NORMALMAP_11 : NormalMap_11
SPECULARMAP : SpecularMap
ALPHAMAP : AlphaMap
ALPHAMAP_1 : AlphaMap_1
ALPHAMAP_2 : AlphaMap_2
DIFFUSEMAP_0_SCALE : DiffuseMap_0_scale
DIFFUSEMAP_1_SCALE : DiffuseMap_1_scale
DIFFUSEMAP_2_SCALE : DiffuseMap_2_scale
DIFFUSEMAP_3_SCALE : DiffuseMap_3_scale
DIFFUSEMAP_4_SCALE : DiffuseMap_4_scale
DIFFUSEMAP_5_SCALE : DiffuseMap_5_scale
DIFFUSEMAP_6_SCALE : DiffuseMap_6_scale
DIFFUSEMAP_7_SCALE : DiffuseMap_7_scale
DIFFUSEMAP_8_SCALE : DiffuseMap_8_scale
DIFFUSEMAP_9_SCALE : DiffuseMap_9_scale
DIFFUSEMAP_10_SCALE : DiffuseMap_10_scale
DIFFUSEMAP_11_SCALE : DiffuseMap_11_scale
}
}
Technique PreShadow { Technique PreShadow {
VertexShader GLSL100 : Common/MatDefs/Shadow/PreShadow.vert VertexShader GLSL100 : Common/MatDefs/Shadow/PreShadow.vert

View File

@ -1,3 +1,5 @@
#import "Common/ShaderLib/Lighting.glsllib"
uniform mat4 g_WorldViewProjectionMatrix; uniform mat4 g_WorldViewProjectionMatrix;
uniform mat4 g_WorldViewMatrix; uniform mat4 g_WorldViewMatrix;
uniform mat3 g_NormalMatrix; uniform mat3 g_NormalMatrix;
@ -34,16 +36,6 @@ varying vec4 SpecularSum;
varying vec3 wNormal; varying vec3 wNormal;
#endif #endif
// JME3 lights in world space
void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){
float posLight = step(0.5, color.w);
vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);
lightVec.xyz = tempVec;
float dist = length(tempVec);
lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);
lightDir.xyz = tempVec / vec3(dist);
}
void main(){ void main(){
vec4 pos = vec4(inPosition, 1.0); vec4 pos = vec4(inPosition, 1.0);
@ -69,14 +61,14 @@ void main(){
vec3 wvTangent = normalize(g_NormalMatrix * inTangent.xyz); vec3 wvTangent = normalize(g_NormalMatrix * inTangent.xyz);
vec3 wvBinormal = cross(wvNormal, wvTangent); vec3 wvBinormal = cross(wvNormal, wvTangent);
mat3 tbnMat = mat3(wvTangent, wvBinormal * -inTangent.w,wvNormal); mat3 tbnMat = mat3(wvTangent, wvBinormal * inTangent.w,wvNormal);
vPosition = wvPosition * tbnMat; vPosition = wvPosition * tbnMat;
vViewDir = viewDir * tbnMat; vViewDir = viewDir * tbnMat;
lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir);
lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz; vLightDir.xyz = (vLightDir.xyz * tbnMat).xyz;
#else #else
//------------------------- //-------------------------
// general to all lighting // general to all lighting
//------------------------- //-------------------------
@ -85,16 +77,11 @@ void main(){
vPosition = wvPosition; vPosition = wvPosition;
vViewDir = viewDir; vViewDir = viewDir;
lightComputeDir(wvPosition, lightColor, wvLightPos, vLightDir); lightComputeDir(wvPosition, lightColor.w, wvLightPos, vLightDir, lightVec);
#endif #endif
//computing spot direction in view space and unpacking spotlight cos AmbientSum = g_AmbientLightColor; // Default: ambient color is dark gray
// spotVec=(g_ViewMatrix *vec4(g_LightDirection.xyz,0.0) );
// spotVec.w=floor(g_LightDirection.w)*0.001;
// lightVec.w = fract(g_LightDirection.w);
AmbientSum = vec4(0.2, 0.2, 0.2, 1.0) * g_AmbientLightColor; // Default: ambient color is dark gray
DiffuseSum = lightColor; DiffuseSum = lightColor;
SpecularSum = lightColor; SpecularSum = lightColor;