MetalArrayTexture/AAPLTerrain.mm
/* |
Copyright (C) 2015 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Utility class for creating a terrain object. |
*/ |
#ifdef TARGET_IOS |
#import <UIKit/UIKit.h> |
#else |
#import <AppKit/AppKit.h> |
#endif |
#import <QuartzCore/QuartzCore.h> |
#import <Metal/Metal.h> |
#import <simd/simd.h> |
#import "AAPLTerrain.h" |
#import "GeoUtils.h" |
const uint32_t kHeightMapDefaultSize = 64; |
@interface AAPLTerrain () |
@property (nonatomic, readwrite) uint32_t heightMapSize; |
@property (nonatomic, readwrite) uint32_t numOfSlices; |
@end |
@implementation AAPLTerrain |
{ |
@private |
id <MTLBuffer> m_IndexBuffer; |
id <MTLBuffer> m_VertexBuffer; |
NSUInteger _indexCount; |
// height map |
GLfloat* _map; |
// Indicies |
NSUInteger _vertexIndex; |
NSUInteger _texCoordIndex; |
NSUInteger _samplerIndex; |
} |
- (instancetype) initWithDevice:(id <MTLDevice>)device |
{ |
self = [super init]; |
if(self) |
{ |
self.heightMapSize = kHeightMapDefaultSize; |
self.numOfSlices = self.heightMapSize - 1; |
[self createTerrainWithDevice:device]; |
_vertexIndex = 0; |
_texCoordIndex = 1; |
_samplerIndex = 0; |
} |
return self; |
} |
- (void)createTerrainWithDevice:(id <MTLDevice>)device |
{ |
if (!device) |
{ |
NSLog(@">> ERROR: Invalid device!"); |
return; |
} |
// Generate a heightmap |
// You can play around with the terrain generation here... |
_map = GenHeightMap(_heightMapSize, _heightMapSize, 0xDEADBEEF); |
//_map = GenHeightMap(_heightMapSize, _heightMapSize, 0xBEEFBEEF); |
// Now let's load this heightmap into the buffers |
// vertex buffer.. |
size_t bufsize = _heightMapSize*_heightMapSize*3*sizeof(GLfloat); |
GLfloat* buf = (GLfloat*)malloc(bufsize); |
// the map buffer has 6 floats per vertex, position and normal |
// we are skipping the normals here since they are not used in our sample shader |
for (int n=0; n < _heightMapSize*_heightMapSize; n++) |
memcpy(&buf[n*3], &_map[n*6], sizeof(GLfloat)*3); |
// index buffer.. |
_indexCount = (_heightMapSize-1) * (_heightMapSize*2+2); |
size_t indexBufsize = _indexCount * sizeof(uint16_t); |
uint16_t* indexBuf = (uint16_t*)malloc(indexBufsize); |
int i, j, ndx = 0; |
// This loads the terrain in, as vertical slices (think a cross section) |
// We load from the current row and row+1 to fill out the tristrips |
// number of slices = heightMapSize - 1 |
for (j = 0; j < _heightMapSize-1; j++) |
{ |
for (i = 0; i < _heightMapSize; i++) |
{ |
// add an additional index to create degenerate triangles between consistent terrain strips |
if (i == 0) { |
indexBuf[ndx++] = (j *_heightMapSize + i); |
} |
indexBuf[ndx++] = (j *_heightMapSize + i); |
indexBuf[ndx++] = ((j+1) *_heightMapSize + i); |
// add an additional index to create degenerate triangles between consistent terrain strips |
if (i == _heightMapSize-1) { |
indexBuf[ndx++] = ((j+1) *_heightMapSize + i); |
} |
} |
} |
m_VertexBuffer = [device newBufferWithBytes:buf |
length:bufsize |
options:MTLResourceOptionCPUCacheModeDefault]; |
if(!m_VertexBuffer) |
{ |
NSLog(@">> ERROR: Failed creating vertex buffer!"); |
return; |
} |
m_IndexBuffer = [device newBufferWithBytes:indexBuf |
length:indexBufsize |
options:MTLResourceOptionCPUCacheModeDefault]; |
if(!m_IndexBuffer) |
{ |
NSLog(@">> ERROR: Failed creating index buffer!"); |
return; |
} |
free(buf); |
free(indexBuf); |
} |
- (void)encode:(id <MTLRenderCommandEncoder>)renderEncoder |
{ |
[renderEncoder setVertexBuffer:m_VertexBuffer |
offset:0 |
atIndex:_vertexIndex]; |
// we use the vertex coordinates as texture coordinates too to index into the array texture |
[renderEncoder setVertexBuffer:m_VertexBuffer |
offset:0 |
atIndex:_texCoordIndex]; |
} |
- (void)draw:(id <MTLRenderCommandEncoder>)renderEncoder |
{ |
[renderEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangleStrip |
indexCount:_indexCount |
indexType:MTLIndexTypeUInt16 |
indexBuffer:m_IndexBuffer |
indexBufferOffset:0 |
instanceCount:1]; |
} |
@end |
Copyright © 2016 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2016-03-21